sync from Azure to LF 15/1215/1
authorss412g <shuky.har-noy@intl.att.com>
Thu, 24 Oct 2019 06:29:26 +0000 (09:29 +0300)
committerss412g <shuky.har-noy@intl.att.com>
Thu, 24 Oct 2019 06:29:49 +0000 (09:29 +0300)
Change-Id: I9daba071938fd021b277d8d17d3c0822d23ac100
Signed-off-by: ss412g <shuky.har-noy@intl.att.com>
159 files changed:
Automation/Dockerfile
Automation/FAILED_TESTS/Reset_unhappy.robot [moved from Automation/Tests/Reset_RIC_TO_RAN/Reset_unhappy.robot with 100% similarity, mode: 0644]
Automation/Scripts/run.sh
Automation/Tests/ConfigurationUpdate/ConfigurationUpdate_Verify_logs.robot
Automation/Tests/ConfigurationUpdate/ConfigurationUpdate_prepartations_tests.robot
Automation/Tests/ConfigurationUpdate/verifylogs.py [deleted file]
Automation/Tests/ENDC-Setup/ENDC_Setup_request_test.robot
Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_RAN_Found.robot [moved from Automation/Tests/Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot with 80% similarity, mode: 0644]
Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_Verify_logs.robot [new file with mode: 0644]
Automation/Tests/ENDC_Reset_RAN_TO_RIC/__init__.robot [moved from Automation/Tests/LoadInfomation/config.py with 91% similarity]
Automation/Tests/ENDC_Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot [new file with mode: 0644]
Automation/Tests/ENDC_Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot [new file with mode: 0644]
Automation/Tests/ENDC_Reset_RIC_TO_RAN/__init__.robot [moved from Automation/Tests/Reset_RAN_TO_RIC/__init__.robot with 93% similarity]
Automation/Tests/Get-All-Nodes-Real/Get_all_nodes_run_setup_and_get_all.robot
Automation/Tests/Get-All-Nodes/Get_nodes_Add_nodes_and_get.robot
Automation/Tests/Health/get_health_check.robot
Automation/Tests/Health/get_health_check_unhappy.robot [moved from Automation/Tests/Unhappy/Response500.robot with 85% similarity, mode: 0644]
Automation/Tests/LoadInfomation/Loadinformation_adding_data_and_overwrite.robot
Automation/Tests/LoadInfomation/Loadinformation_verify_saving.robot
Automation/Tests/Lost_Connection/Lost_Connetion_CONNECTING_TO_DISCONNECTED.robot
Automation/Tests/RedButton/RedButton_CONNECTED_SHUTDOWN_CONNECTED.robot
Automation/Tests/RedButton/RedButton_DISCONNECTED.robot
Automation/Tests/Reset_RAN_TO_RIC/Reset_Ran_To_Ric_Verify_logs.py [deleted file]
Automation/Tests/Reset_RAN_TO_RIC_2/Reset_Ran_To_Ric_RNIB_Down_Verify_logs.py [deleted file]
Automation/Tests/Resource/Keywords.robot
Automation/Tests/Resource/config.py [deleted file]
Automation/Tests/Resource/resource.robot
Automation/Tests/Resource/scripts_variables.robot [new file with mode: 0644]
Automation/Tests/Scripts/cleanup_db.py [moved from Automation/Tests/Resource/scripts.py with 100% similarity]
Automation/Tests/Scripts/config.py [moved from Automation/Tests/Get-All-Nodes/config.py with 100% similarity, mode: 0644]
Automation/Tests/Scripts/find_error_script.py [new file with mode: 0644]
Automation/Tests/Scripts/find_rmr_message.py [new file with mode: 0644]
Automation/Tests/Scripts/getnodes.py [moved from Automation/Tests/Get-All-Nodes/getnodes.py with 100% similarity]
Automation/Tests/Scripts/loadscripts.py [moved from Automation/Tests/LoadInfomation/loadscripts.py with 100% similarity]
Automation/Tests/Unhappy/Get_All_Nodedb_HttpResponse500.robot [new file with mode: 0644]
Automation/Tests/Unhappy/Get_Nodeb_HttpResponse404.robot [moved from Automation/Tests/Unhappy/Resource_not_found.robot with 100% similarity, mode: 0644]
Automation/Tests/Unhappy/Get_Nodeb_HttpResponse500.robot [new file with mode: 0644]
Automation/Tests/Unhappy/RedButton_HttpResponse500.robot [new file with mode: 0644]
Automation/Tests/Unhappy/Reset_HttpResponse400.robot [moved from Automation/Tests/Reset_RAN_TO_RIC_2/Reset_RNIB.robot with 69% similarity]
Automation/Tests/Unhappy/Reset_HttpResponse400_wrongstate.robot [new file with mode: 0644]
Automation/Tests/Unhappy/Reset_HttpResponse404.robot [moved from Automation/Tests/Unhappy/Response400.robot with 82% similarity, mode: 0644]
Automation/Tests/Unhappy/Setup_Request_HttpResponse400.robot [new file with mode: 0644]
Automation/Tests/Unhappy/Setup_Request_HttpResponse500.robot [new file with mode: 0644]
Automation/Tests/Unhappy/Setup_Request_setup_failure.robot [moved from Automation/Tests/Unhappy/Setup_failure.robot with 94% similarity, mode: 0644]
Automation/Tests/X2-Setup/X2_Setup_reuqest_test.robot
Automation/Tests/X2_Reset_RAN_TO_RIC/Reset_RAN_Found.robot [moved from Automation/Tests/Reset_RAN_TO_RIC/Reset_RAN_Found.robot with 88% similarity]
Automation/Tests/X2_Reset_RAN_TO_RIC/Reset_Verify_logs.robot [moved from Automation/Tests/Reset_RAN_TO_RIC/Reset_Verify_logs.robot with 50% similarity]
Automation/Tests/X2_Reset_RAN_TO_RIC/__init__.robot [moved from Automation/Tests/Reset_RAN_TO_RIC_2/__init__.robot with 93% similarity]
Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/Reset_RNIB.robot [moved from Automation/Tests/Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot with 87% similarity, mode: 0644]
Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/Reset_Verify_logs.robot [moved from Automation/Tests/Reset_RAN_TO_RIC_2/Reset_Verify_logs.robot with 59% similarity]
Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/__init__.robot [new file with mode: 0644]
Automation/Tests/X2_Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot [new file with mode: 0644]
Automation/Tests/X2_Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot [new file with mode: 0644]
Automation/Tests/X2_Reset_RIC_TO_RAN/__init__.robot [moved from Automation/Tests/Reset_RIC_TO_RAN/__init__.robot with 94% similarity, mode: 0644]
E2Manager/Dockerfile
E2Manager/app/main.go [new file with mode: 0644]
E2Manager/configuration/configuration.go
E2Manager/configuration/configuration_test.go [new file with mode: 0644]
E2Manager/container-tag.yaml
E2Manager/controllers/controller.go [deleted file]
E2Manager/controllers/controller_test.go [deleted file]
E2Manager/controllers/nodeb_controller.go
E2Manager/controllers/nodeb_controller_test.go
E2Manager/controllers/root_controller.go [new file with mode: 0644]
E2Manager/controllers/root_controller_test.go [new file with mode: 0644]
E2Manager/converters/enb_load_information_extractor.go [moved from E2Manager/converters/enb_load_information_to_protobuf.go with 98% similarity]
E2Manager/converters/enb_load_information_extractor_test.go [moved from E2Manager/converters/enb_load_information_to_protobuf_test.go with 100% similarity]
E2Manager/converters/x2_reset_response_extractor.go [new file with mode: 0644]
E2Manager/converters/x2_setup_failure_response_converter.go [moved from E2Manager/converters/x2setupFailureResponseToProtobuf.go with 90% similarity]
E2Manager/converters/x2_setup_failure_response_converter_test.go [moved from E2Manager/converters/x2setupFailureResponseToProtobuf_test.go with 58% similarity]
E2Manager/converters/x2_setup_response_converter.go [moved from E2Manager/converters/x2setupResponseToProtobuf.go with 89% similarity]
E2Manager/converters/x2_setup_response_converter_test.go [moved from E2Manager/converters/x2setupResponseToProtobuf_test.go with 99% similarity]
E2Manager/e2managererrors/wrong_state_error.go
E2Manager/enums/message_direction.go [new file with mode: 0644]
E2Manager/go.sum
E2Manager/handlers/httpmsghandlers/delete_all_request_handler.go
E2Manager/handlers/httpmsghandlers/delete_all_request_handler_test.go
E2Manager/handlers/httpmsghandlers/get_nodeb_id_list_request_handler.go [new file with mode: 0644]
E2Manager/handlers/httpmsghandlers/get_nodeb_id_list_request_handler_test.go [new file with mode: 0644]
E2Manager/handlers/httpmsghandlers/get_nodeb_request_handler.go [new file with mode: 0644]
E2Manager/handlers/httpmsghandlers/get_nodeb_request_handler_test.go [new file with mode: 0644]
E2Manager/handlers/httpmsghandlers/request_handler.go
E2Manager/handlers/httpmsghandlers/setup_request_handler.go
E2Manager/handlers/httpmsghandlers/setup_request_handler_test.go
E2Manager/handlers/httpmsghandlers/x2_reset_request_handler.go
E2Manager/handlers/httpmsghandlers/x2_reset_request_handler_test.go
E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler.go
E2Manager/handlers/rmrmsghandlers/e2_term_init_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/enb_load_information_notification_handler.go
E2Manager/handlers/rmrmsghandlers/enb_load_information_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/endc_configuration_update_handler.go
E2Manager/handlers/rmrmsghandlers/endc_configuration_update_handler_test.go
E2Manager/handlers/rmrmsghandlers/notification_handler.go
E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler.go
E2Manager/handlers/rmrmsghandlers/ran_lost_connection_handler_test.go
E2Manager/handlers/rmrmsghandlers/setup_response_notification_handler.go
E2Manager/handlers/rmrmsghandlers/setup_response_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/x2_reset_request_notification_handler.go
E2Manager/handlers/rmrmsghandlers/x2_reset_request_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/x2_reset_response_handler.go
E2Manager/handlers/rmrmsghandlers/x2_reset_response_handler_test.go
E2Manager/handlers/rmrmsghandlers/x2enb_configuration_update_handler.go
E2Manager/handlers/rmrmsghandlers/x2enb_configuration_update_handler_test.go
E2Manager/httpserver/http_server.go [new file with mode: 0644]
E2Manager/httpserver/http_server_test.go [new file with mode: 0644]
E2Manager/main/http_server.go [deleted file]
E2Manager/main/http_server_test.go [deleted file]
E2Manager/managers/notificationmanager/notification_manager.go
E2Manager/managers/notificationmanager/notification_manager_test.go [new file with mode: 0644]
E2Manager/managers/ran_reconnection_manager_test.go
E2Manager/managers/ran_setup_manager.go
E2Manager/managers/ran_setup_manager_test.go
E2Manager/managers/ran_status_change_manager.go [new file with mode: 0644]
E2Manager/managers/ran_status_change_manager_test.go [new file with mode: 0644]
E2Manager/managers/x2_setup_failure_response_manager.go
E2Manager/managers/x2_setup_response_manager.go
E2Manager/mocks/controllerMock.go
E2Manager/mocks/rmrMessengerMock.go
E2Manager/models/e2_request_message.go
E2Manager/models/get_nodeb_id_list_response.go [new file with mode: 0644]
E2Manager/models/get_nodeb_request.go [moved from E2Manager/models/notification_response.go with 73% similarity]
E2Manager/models/get_nodeb_response.go [new file with mode: 0644]
E2Manager/models/i_response.go [new file with mode: 0644]
E2Manager/models/resource_status_payload.go [new file with mode: 0644]
E2Manager/models/rmr_message.go [new file with mode: 0644]
E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go
E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go
E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go
E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go
E2Manager/resources/configuration.yaml
E2Manager/rmrCgo/rmrCgoApi.go
E2Manager/rmrCgo/rmrCgoApi_test.go
E2Manager/rmrCgo/rmrCgoTypes.go
E2Manager/router.txt
E2Manager/services/receivers/rmr_service_receiver.go [deleted file]
E2Manager/services/rmr_service.go [deleted file]
E2Manager/services/rmr_service_test.go [deleted file]
E2Manager/services/rmrreceiver/rmr_receiver.go [new file with mode: 0644]
E2Manager/services/rmrreceiver/rmr_receiver_test.go [moved from E2Manager/services/receivers/rmr_service_receiver_test.go with 56% similarity]
E2Manager/services/rmrsender/rmr_sender.go [new file with mode: 0644]
E2Manager/services/rmrsender/rmr_sender_test.go [new file with mode: 0644]
E2Manager/services/rnib_data_service.go
E2Manager/services/rnib_data_service_test.go
E2Manager/stateMachine/delete_all_node_state_machine_test.go [new file with mode: 0644]
E2Manager/utils/time_utils.go [new file with mode: 0644]
Swagger/E2Manager_API.yaml [new file with mode: 0644]
router.txt [deleted file]
tools/xapp_mock/Dockerfile [new file with mode: 0644]
tools/xapp_mock/configuration.json [new file with mode: 0644]
tools/xapp_mock/frontend/configfile.go [new file with mode: 0644]
tools/xapp_mock/frontend/jsonDecoder.go [new file with mode: 0644]
tools/xapp_mock/main/xapp_mock.go [new file with mode: 0644]
tools/xapp_mock/resources/router.txt [new file with mode: 0644]
tools/xapp_mock/resp [new file with mode: 0644]
tools/xapp_mock/rmr/rmrCgoApi.go [new file with mode: 0644]
tools/xapp_mock/rmr/rmrCgoTypes.go [new file with mode: 0644]
tools/xapp_mock/rmr/rmrCgoUtils.go [new file with mode: 0644]
tools/xapp_mock/rmr/rmrEndPoint.go [new file with mode: 0644]
tools/xapp_mock/sender/jsonSender.go [new file with mode: 0644]

index 18a6be7..6733a6b 100755 (executable)
@@ -1,11 +1,9 @@
-root@ric01:/opt/docker# cat Dockerfile 
 FROM python:3.6
 
 RUN python3 -m pip install robotframework \
-    && pip3 install --upgrade RESTinstance \
+    && pip install --upgrade RESTinstance \
     && pip install docker \
-    && apt-get update \
-    && apt-get install -y vim
+    && apt-get update 
 
 WORKDIR /opt
 COPY ./Scripts /opt/Scripts
index 64cf841..e3fb919 100755 (executable)
@@ -1,58 +1,66 @@
 #!/bin/bash 
 
 COMP="${1:-all}"
-E2M_TAG="${2:-1.0.0}"
-E2T_TAG="${3:-1.0.0}"
-SIM_TAG="${4:-1.0.5}"
+E2M_TAG="${2:-2.0.6}"
+E2T_TAG="${3:-2.0.6}"
+SIM_TAG="${4:-1.0.6}"
+E2ADAPTER_TAG="${5:-1.3.2}"
 
 if [ "$COMP" == "all" ]; then
 docker rm -f e2
 docker rm -f e2mgr
 docker rm -f gnbe2_simu
+docker rm -f e2adapter
+docker rm -f dbass
 
-docker kill redis
-docker rm redis
-docker run -d --name redis -p 6379:6379 --env DBAAS_SERVICE_HOST=10.0.2.15  snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/dbass:1.0.0
-
+docker ps
 sleep 2
 
-docker pull nexus3.o-ran-sc.org:10004/ric-plt-e2:$E2T_TAG
-docker pull nexus3.o-ran-sc.org:10004/ric-plt-e2mgr:$E2M_TAG
-docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_sim:$SIM_TAG
+#docker pull nexus3.o-ran-sc.org:10004/ric-plt-e2:$E2T_TAG
+#docker pull nexus3.o-ran-sc.org:10004/ric-plt-e2mgr:$E2M_TAG
+docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2:$E2T_TAG
+docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2mgr:$E2M_TAG
+docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:$SIM_TAG
+docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2adapter:$E2ADAPTER_TAG
+docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/dbass:1.0.0
+
+docker run -d --name dbass -p 6379:6379 --env DBAAS_SERVICE_HOST=10.0.2.15  snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/dbass:1.0.0
 
-docker run -d --name e2mgr -p 3800:3800 -p 3801:3801 --env DBAAS_SERVICE_HOST=10.0.2.15 --env RIC_ID="bbbccc-abcd0e/20" nexus3.o-ran-sc.org:10004/ric-plt-e2mgr:$E2M_TAG
-docker cp e2mgr:/opt/E2Manager/router.txt .
+#docker run -d --name e2mgr -p 3800:3800 -p 3801:3801 --env DBAAS_SERVICE_HOST=10.0.2.15 --env RIC_ID="bbbccc-abcd0e/20" --env RMR_VCTL_FILE=/tmp/rmr.verbose nexus3.o-ran-sc.org:10004/ric-plt-e2mgr:$E2M_TAG
+docker run -d --name e2mgr -p 3800:3800 -p 3801:3801 --env DBAAS_SERVICE_HOST=10.0.2.15 --env RIC_ID="bbbccc-abcd0e/20" --env RMR_VCTL_FILE=/tmp/rmr.verbose snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2mgr:$E2M_TAG
+#docker cp e2mgr:/opt/E2Manager/router.txt .
 sleep 2
-docker create --name e2 --env sctp=5577 --env nano=38000 --env loglevel=debug --env print=1 -p 38000:38000 nexus3.o-ran-sc.org:10004/ric-plt-e2:$E2T_TAG
+#docker create --name e2 --env sctp=5577 --env nano=38000 --env loglevel=debug --env print=1 -p 38000:38000 nexus3.o-ran-sc.org:10004/ric-plt-e2:$E2T_TAG
+docker create --name e2 --env sctp=5577 --env nano=38000 --env loglevel=debug --env print=1 -p 38000:38000 snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2:$E2T_TAG
 sleep 2
-docker cp router.txt e2:/opt/e2/dockerRouter.txt
+#docker cp router.txt e2:/opt/e2/dockerRouter.txt
 sleep 2
 docker start e2
 
-docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422  --env duration=600000000000 --env indicationReportRate=0 --env indicationInsertRate=0 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_sim:$SIM_TAG
+docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422 --env indicationReportRate=0 --env indicationInsertRate=0 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:$SIM_TAG
 
-#docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422  --env duration=600000000000 --env indicationReportRate=1000000 --env indicationInsertRate=1000000 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.0
+docker run -d -v /etc/e2adapter:/etc/e2adapter -v /var/log/e2adapter:/var/log/e2adapter --network host --name e2adapter snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2adapter:$E2ADAPTER_TAG
 
 docker ps
 fi
 if [ "$COMP" = "gnbe2_sim" ]; then
 docker rm -f gnb_simu
-#docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422  --env duration=600000000000 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:$SIM_TAG
-#docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnb_simu:1.1.0
-docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422 --env duration=6000000000000 indicationReportRate=0 --env indicationInsertRate=0 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_sim:$SIM_TAG
+docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422 indicationReportRate=0 --env indicationInsertRate=0 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:$SIM_TAG
 docker ps
 fi
 if [ "$COMP" = "e2" ]; then
 docker rm -f e2
-docker pull nexus3.o-ran-sc.org:10004/ric-plt-e2:$E2T_TAG
+#docker pull nexus3.o-ran-sc.org:10004/ric-plt-e2:$E2T_TAG
+docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2:$E2T_TAG
 docker create --name e2 --env sctp=5577 --env nano=38000 --env print=1 --env RMR_RTG_SVC=10.0.2.15 -p 38000:38000 snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2:$E2T_TAG
 
 docker ps
 fi
 if [ "$COMP" = "e2mgr" ]; then
 docker rm -f e2mgr
-docker pull nexus3.o-ran-sc.org:10004/ric-plt-e2mgr:$E2M_TAG
-docker run -d --name e2mgr -p 3800:3800 -p 3801:3801 --env RMR_RTG_SVC=10.0.2.15 --env DBAAS_SERVICE_HOST=10.0.2.15 RIC_ID="bbbccc-abcd0e/20" nexus3.o-ran-sc.org:10004/ric-plt-e2mgr:$E2M_TAG
+#docker pull nexus3.o-ran-sc.org:10004/ric-plt-e2mgr:$E2M_TAG
+docker pull snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2mgr:$E2M_TAG
+#docker run -d --name e2mgr -p 3800:3800 -p 3801:3801 --env RMR_RTG_SVC=10.0.2.15 --env DBAAS_SERVICE_HOST=10.0.2.15 RIC_ID="bbbccc-abcd0e/20" nexus3.o-ran-sc.org:10004/ric-plt-e2mgr:$E2M_TAG
+docker run -d --name e2mgr -p 3800:3800 -p 3801:3801 --env RMR_RTG_SVC=10.0.2.15 --env DBAAS_SERVICE_HOST=10.0.2.15 RIC_ID="bbbccc-abcd0e/20" snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/e2mgr:$E2M_TAG
 docker ps
-fi
-
+fi
\ No newline at end of file
index bc786be..9b209b0 100755 (executable)
 
 
 *** Settings ***
+Resource   ../Resource/resource.robot
+Resource    ../Resource/scripts_variables.robot
 Library     String
 Library     OperatingSystem
 Library     Process
-Library     ${CURDIR}/verifylogs.py
+Library     ../Scripts/find_rmr_message.py
+
 
 
 *** Test Cases ***
 Verify logs - Confiugration update - Begin Tag Get
     ${Configuration}=   Grep File  ./gnb.log  <ENDCConfigurationUpdate>
-    #Log to console      ${Configuration}
     ${ConfigurationAfterStrip}=     Strip String    ${Configuration}
     Should Be Equal     ${ConfigurationAfterStrip}        <ENDCConfigurationUpdate>
 
 Verify logs - Confiugration update - End Tag Get
     ${ConfigurationEnd}=   Grep File  ./gnb.log  </ENDCConfigurationUpdate>
-    #Log to console      ${ConfigurationEnd}
     ${ConfigurationEndAfterStrip}=     Strip String    ${ConfigurationEnd}
     Should Be Equal     ${ConfigurationEndAfterStrip}        </ENDCConfigurationUpdate>
 
 Verify logs - Confiugration update - Ack Tag Begin
     ${ConfigurationAck}=   Grep File  ./gnb.log   <ENDCConfigurationUpdateAcknowledge>
-    #Log to console      ${ConfigurationEnd}
     ${ConfigurationAckAfter}=     Strip String    ${ConfigurationAck}
     Should Be Equal     ${ConfigurationAckAfter}        <ENDCConfigurationUpdateAcknowledge>
 
 Verify logs - Confiugration update - Ack Tag End
     ${ConfigurationAckEnd}=   Grep File  ./gnb.log  </ENDCConfigurationUpdateAcknowledge>
-    #Log to console      ${ConfigurationEnd}
     ${ConfigurationAckEndAfterStrip}=     Strip String    ${ConfigurationAckEnd}
     Should Be Equal     ${ConfigurationAckEndAfterStrip}        </ENDCConfigurationUpdateAcknowledge>
 
-Verify logs - e2mgr logs
-   ${result}    verifylogs.verify   ${EXECDIR}
-   Should Be Equal As Strings    ${result}      True
\ No newline at end of file
+Verify logs - find RIC_ENDC_CONF_UPDATE
+   ${result}   find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${configurationupdate_message_type}  ${Meid_test1}
+   Should Be Equal As Strings    ${result}      True
+Verify logs - find RIC_ENDC_CONF_UPDATE_ACK
+   ${result1}  find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${configurationupdate_ack_message_type}  ${Meid_test1}
+   Should Be Equal As Strings    ${result1}      True
index 2aec47f..9998294 100644 (file)
@@ -30,20 +30,17 @@ Library     REST      ${url}
 X2 - Setup and Get
     Post Request setup node b x-2
     Get Request node b enb test1
+    String   response body connectionStatus    CONNECTED
 
 
 Run Configuration update
     Run    ${Run_Config}
     Sleep   1s
 
-Remove log files
-    Remove File  ${EXECDIR}/gnb.log
-    Remove File  ${EXECDIR}/e2mgr.log
+Prepare logs for tests
+    Remove log files
+    Save logs
 
-Save logs
-    Sleep   1s
-    Run     ${Save_e2_log}
-    Run     ${Save_e2mgr_log}
 
 
 
diff --git a/Automation/Tests/ConfigurationUpdate/verifylogs.py b/Automation/Tests/ConfigurationUpdate/verifylogs.py
deleted file mode 100755 (executable)
index fdfd64a..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-##############################################################################
-#
-#   Copyright (c) 2019 AT&T Intellectual Property.
-#
-#   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.
-#
-##############################################################################
-
-
-def verify(directory):
-
-    file = 'e2mgr.log'
-
-    path = '/'
-
-    file_path = directory + path + file
-
-    f = open(file_path,'r')
-
-    found_message_10370 = False
-    found_message_10371 = False
-
-    for l in f:
-        if l.find('MType: 10370') > 0 and l.find('Meid: \\"test1\\"') > 0:
-            found_message_10370 = True
-        elif l.find('MType: 10371') > 0 and l.find('Meid: \\"test1\\"') > 0:
-            found_message_10371 = True
-        if found_message_10370 and found_message_10371:
-            break
-
-    if found_message_10370 and found_message_10371:
-        return True
-    else:
-        return False
-
-
-
index 33db346..285a2a3 100755 (executable)
@@ -20,8 +20,9 @@
 Suite Setup   Prepare Enviorment
 Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
+Resource    ../Resource/scripts_variables.robot
 Library     OperatingSystem
-Library    Collections
+Library     ../Scripts/find_rmr_message.py
 Library     REST        ${url}
 
 
@@ -37,7 +38,7 @@ Get request gnb
     Get Request node b enb test2
     Integer  response status  200
     String   response body ranName    test2
-    String   response body ip    10.0.2.15
+    String   response body ip    ${ip_e2adapter} 
     String   response body connectionStatus    CONNECTED
     Integer  response body port     49999
     String   response body nodeType     GNB
@@ -52,6 +53,18 @@ Get request gnb
     String   response body gnb servedNrCells 0 servedNrCellInformation choiceNrMode tdd transmissionBandwidth nrscs   SCS30
     String  response body gnb servedNrCells 0 servedNrCellInformation choiceNrMode tdd transmissionBandwidth ncnrb   NRB162
 
+prepare logs for tests
+    Remove log files
+    Save logs
+
+
+ENDC - RAN Connected message going to be sent
+    ${result}    find_rmr_message.verify_logs   ${EXECDIR}   ${e2mgr_log_filename}  ${RAN_CONNECTED_message_type}    ${Meid_test2}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message not sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
+    Should Be Equal As Strings    ${result}      False
 
 
 
old mode 100755 (executable)
new mode 100644 (file)
similarity index 80%
rename from Automation/Tests/Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot
rename to Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_RAN_Found.robot
index 7d03300..cb91c0d
@@ -17,7 +17,7 @@
 ##############################################################################
 
 *** Settings ***
-Suite Setup  Prepare Enviorment
+Suite Setup   Prepare Enviorment
 Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
@@ -25,18 +25,24 @@ Library     Collections
 Library     REST      ${url}
 
 
+
+
 *** Test Cases ***
+
 Prepare Ran in Connected connectionStatus
-    Post Request setup node b x-2
+    Post Request setup node b endc-setup
     Integer     response status       204
     Sleep  1s
-    GET      /v1/nodeb/test1
+    GET      /v1/nodeb/test2
     Integer  response status  200
-    String   response body ranName    test1
+    String   response body ranName    test2
     String   response body connectionStatus    CONNECTED
 
+Run Reset from RAN
+    Run    ${Run_Config}
+    Sleep   1s
+
+Prepare logs for tests
+    Remove log files
+    Save logs
 
-Send Reset reqeust with cause
-    Set Headers     ${header}
-    PUT    /v1/nodeb/test1/reset    ${resetcausejson}
-    Integer  response status  204
\ No newline at end of file
diff --git a/Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_Verify_logs.robot b/Automation/Tests/ENDC_Reset_RAN_TO_RIC/Reset_Verify_logs.robot
new file mode 100644 (file)
index 0000000..e844ccf
--- /dev/null
@@ -0,0 +1,50 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+
+*** Settings ***
+Resource    ../Resource/scripts_variables.robot
+Resource   ../Resource/Keywords.robot
+Library     String
+Library     OperatingSystem
+Library     Process
+Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/find_error_script.py
+
+
+
+*** Test Cases ***
+Verify logs - Reset Sent by e2adapter
+    ${result}    find_error_script.find_error  ${EXECDIR}  ${e2adapter_log_filename}  ${E2ADAPTER_Setup_Resp}
+    Should Be Equal As Strings    ${result}      True
+
+Verify logs - e2mgr logs - messege sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+Verify logs - e2mgr logs - messege received
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_RESP_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RAN Restarted messege sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message not sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
+    Should Be Equal As Strings    ${result}      False
\ No newline at end of file
@@ -16,5 +16,5 @@
 #
 ##############################################################################
 
-redis_ip_address = 'localhost'
-redis_ip_port = 6379
+*** Settings ***
+Documentation    ORAN Reset - ENDC RAN to RIC Scenario 1
diff --git a/Automation/Tests/ENDC_Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot b/Automation/Tests/ENDC_Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot
new file mode 100644 (file)
index 0000000..cccd10b
--- /dev/null
@@ -0,0 +1,56 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource    ../Resource/scripts_variables.robot
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Library     OperatingSystem
+Library     ../Scripts/find_rmr_message.py
+Library     REST      ${url}
+
+
+*** Test Cases ***
+Prepare Ran in Connected connectionStatus
+    Post Request setup node b endc-setup
+    Integer     response status       204
+    Sleep  1s
+    GET      /v1/nodeb/test2
+    Integer  response status  200
+    String   response body ranName    test2
+    String   response body connectionStatus    CONNECTED
+
+
+Send Reset reqeust with no cause
+    Set Headers     ${header}
+    PUT    /v1/nodeb/test2/reset
+    Integer  response status  204
+
+Prepare logs for tests
+    Remove log files
+    Save logs
+
+
+RAN Restarted messege sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}    ${Meid_test2}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message not sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
+    Should Be Equal As Strings    ${result}      False
\ No newline at end of file
diff --git a/Automation/Tests/ENDC_Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot b/Automation/Tests/ENDC_Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot
new file mode 100644 (file)
index 0000000..92cf4f8
--- /dev/null
@@ -0,0 +1,57 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup  Prepare Enviorment
+Resource    ../Resource/scripts_variables.robot
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Library     OperatingSystem
+Library     ../Scripts/find_rmr_message.py
+Library     REST      ${url}
+
+
+*** Test Cases ***
+Prepare Ran in Connected connectionStatus
+    Post Request setup node b endc-setup
+    Integer     response status       204
+    Sleep  1s
+    GET      /v1/nodeb/test2
+    Integer  response status  200
+    String   response body ranName    test2
+    String   response body connectionStatus    CONNECTED
+
+
+Send Reset reqeust with cause
+    Set Headers     ${header}
+    PUT    /v1/nodeb/test2/reset    ${resetcausejson}
+    Integer  response status  204
+
+
+Prepare logs for tests
+    Remove log files
+    Save logs
+
+
+RAN Restarted messege sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}    ${Meid_test2}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message not sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test2}
+    Should Be Equal As Strings    ${result}      False
\ No newline at end of file
@@ -17,4 +17,4 @@
 ##############################################################################
 
 *** Settings ***
-Documentation    ORAN Reset - RAN to RIC Scenario 1
+Documentation    ORAN Reset API - ENDC RIC to RAN
index 7048558..1f32682 100755 (executable)
@@ -32,7 +32,6 @@ Run x2 setup
     GET      /v1/nodeb/test1
     Integer  response status  200
     String   response body ranName    test1
-    String   response body ip    10.0.2.15
     Integer  response body port     5577
     String   response body connectionStatus    CONNECTED
 
@@ -43,7 +42,6 @@ Run endc setup
     GET      /v1/nodeb/test2
     Integer  response status  200
     String   response body ranName    test2
-    String   response body ip    10.0.2.15
     String   response body connectionStatus    CONNECTED
 
 
index 0f77a7a..f6e5b40 100755 (executable)
 *** Settings ***
 Suite Setup   Prepare Enviorment
 Library      Process
+Library     ../Scripts/getnodes.py
 Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
-Library     ${CURDIR}/getnodes.py
 Library     REST      ${url}
 
 
index 8cbacab..8fa9f59 100755 (executable)
@@ -31,10 +31,3 @@ Get Health
     Integer     response status       200
 
 
-*** Keywords ***
-Start dockers
-     Run And Return Rc And Output    ${run_script}
-     ${result}=  Run And Return Rc And Output     ${docker_command}
-     Should Be Equal As Integers    ${result[1]}    4
-
-
old mode 100755 (executable)
new mode 100644 (file)
similarity index 85%
rename from Automation/Tests/Unhappy/Response500.robot
rename to Automation/Tests/Health/get_health_check_unhappy.robot
index 1e99b83..2ca3e26
@@ -22,11 +22,15 @@ Resource   ../Resource/Keywords.robot
 Resource   ../Resource/resource.robot
 Library     OperatingSystem
 Library     REST      ${url}
-Suite Teardown   Start Redis
+Suite Teardown   Start Dbass
+
+
 
 *** Test Cases ***
-Get Request node b gnb - DB down - 500
-    Run   docker stop redis
-    GET      /v1/nodeb/test5
-    Integer  response status   500
+Get Health Unhappy - Dbass down
+    Stop Dbass
+    GET     /v1/health
+    Integer     response status       500
+
+
 
index 91d4960..6600df2 100644 (file)
@@ -21,9 +21,8 @@ Suite Setup  Prepare Simulator For Load Information
 Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
-Library     Collections
 Library     Process
-Library     ${CURDIR}/loadscripts.py
+Library     ../Scripts/loadscripts.py
 Library     REST      ${url}
 Suite Teardown  Stop Simulator
 
index 3702c78..999ad4a 100644 (file)
@@ -21,9 +21,8 @@ Suite Setup  Prepare Simulator For Load Information
 Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
-Library     Collections
 Library     Process
-Library     ${CURDIR}/loadscripts.py
+Library     ../Scripts/loadscripts.py
 Library     REST      ${url}
 Suite Teardown  Stop Simulator
 
index 96ad4f1..02c16cf 100644 (file)
@@ -32,7 +32,7 @@ Library     REST      ${url}
 Pre Condition for Connecting - no simu
     Run And Return Rc And Output    ${stop_simu}
     ${result}=  Run And Return Rc And Output     ${docker_command}
-    Should Be Equal As Integers    ${result[1]}    4
+    Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
 
 
 Prepare Ran in Connecting connectionStatus
index e0f5dd4..8891608 100755 (executable)
@@ -58,7 +58,7 @@ Restart simualtor
 
     Run And Return Rc And Output    ${restart_docker_sim}
     ${result}=  Run And Return Rc And Output     ${docker_command}
-    Should Be Equal As Integers    ${result[1]}    5
+    Should Be Equal As Integers    ${result[1]}    ${docker_number}
 
 
 repare Ran in Connected connectionStatus
index 0c2763a..d3d8285 100755 (executable)
@@ -33,7 +33,7 @@ ${stop_docker_e2}      docker stop e2adapter
 Pre Condition for Connecting - no E2ADAPTER
     Run And Return Rc And Output    ${stop_docker_e2}
     ${result}=  Run And Return Rc And Output     ${docker_command}
-    Should Be Equal As Integers    ${result[1]}    4
+    Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
 
 
 Prepare Ran in Connecting connectionStatus
diff --git a/Automation/Tests/Reset_RAN_TO_RIC/Reset_Ran_To_Ric_Verify_logs.py b/Automation/Tests/Reset_RAN_TO_RIC/Reset_Ran_To_Ric_Verify_logs.py
deleted file mode 100644 (file)
index fd03b24..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-##############################################################################
-#
-#   Copyright (c) 2019 AT&T Intellectual Property.
-#
-#   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.
-#
-##############################################################################
-
-
-def verify(directory):
-
-    file = 'e2mgr.log'
-
-    path = '/'
-
-    file_path = directory + path + file
-
-    f = open(file_path,'r')
-
-    found_message_10070 = False
-    found_message_10071 = False
-
-    for l in f:
-        if l.find('MType: 10070') > 0 and l.find('Meid: \\"test1\\"') > 0:
-            found_message_10070 = True
-        elif l.find('MType: 10071') > 0 and l.find('Meid: \\"test1\\"') > 0:
-            found_message_10071 = True
-
-        if found_message_10070 and found_message_10071:
-            break
-
-    if found_message_10070 and found_message_10071:
-        return True
-    else:
-        return False
-
-
-
diff --git a/Automation/Tests/Reset_RAN_TO_RIC_2/Reset_Ran_To_Ric_RNIB_Down_Verify_logs.py b/Automation/Tests/Reset_RAN_TO_RIC_2/Reset_Ran_To_Ric_RNIB_Down_Verify_logs.py
deleted file mode 100644 (file)
index 1174480..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-##############################################################################
-#
-#   Copyright (c) 2019 AT&T Intellectual Property.
-#
-#   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.
-#
-##############################################################################
-
-
-def verify(directory):
-
-    file = 'e2mgr.log'
-
-    path = '/'
-
-    file_path = directory + path + file
-
-    f = open(file_path,'r')
-
-    found_message_10070 = False
-    found_message_error = False
-
-    for l in f:
-        if l.find('MType: 10070') > 0 and l.find('Meid: \\"test1\\"') > 0:
-            found_message_10070 = True
-        elif l.find('RanName: test1') > 0 and l.find('Error:') > 0:
-            found_message_error = True
-        if found_message_10070 and found_message_error:
-            break
-
-    if found_message_10070 and found_message_error:
-        return True
-    else:
-        return False
-
-
-
index 94fc870..e1d6e63 100755 (executable)
@@ -18,7 +18,7 @@
 
 *** Settings ***
 Documentation   Keywords file
-Library     ${CURDIR}/scripts.py
+Library     ../Scripts/cleanup_db.py
 Resource   ../Resource/resource.robot
 Library     OperatingSystem
 
@@ -43,6 +43,19 @@ Get Request node b enb test2
     GET      /v1/nodeb/test2
 
 
+Remove log files
+    Remove File  ${EXECDIR}/${gnb_log_filename}
+    Remove File  ${EXECDIR}/${e2mgr_log_filename}
+    Remove File  ${EXECDIR}/${rsm_log_filename}
+    Remove File  ${EXECDIR}/${e2adapter_log_filename}
+
+Save logs
+    Sleep   1s
+    Run     ${Save_sim_log}
+    Run     ${Save_e2mgr_log}
+    Run     ${Save_rsm_log}
+    Run     ${Save_e2adapter_log}
+
 
 Post Request setup node b endc-setup
     Set Headers     ${header}
@@ -55,14 +68,14 @@ Stop Simulator
 Prepare Simulator For Load Information
      Run And Return Rc And Output    ${stop_simu}
      Run And Return Rc And Output    ${docker_Remove}
-     ${flush}  scripts.flush
+     ${flush}  cleanup_db.flush
      Should Be Equal As Strings  ${flush}  True
      Run And Return Rc And Output    ${run_simu_load}
      ${result}=  Run And Return Rc And Output     ${docker_command}
-     Should Be Equal As Integers    ${result[1]}    5
+     Should Be Equal As Integers    ${result[1]}    ${docker_number}
 
 Prepare Enviorment
-     ${flush}  scripts.flush
+     ${flush}  cleanup_db.flush
      Should Be Equal As Strings  ${flush}  True
      Run And Return Rc And Output    ${stop_simu}
      Run And Return Rc And Output    ${docker_Remove}
@@ -70,20 +83,24 @@ Prepare Enviorment
      Run And Return Rc And Output    ${restart_e2adapter}
      Sleep  2s
      ${result}=  Run And Return Rc And Output     ${docker_command}
-     log to console   ${result}
-     Should Be Equal As Integers    ${result[1]}    5
+     Should Be Equal As Integers    ${result[1]}    ${docker_number}
 
 Start E2
      Run And Return Rc And Output    ${start_e2}
      ${result}=  Run And Return Rc And Output     ${docker_command}
-     Should Be Equal As Integers    ${result[1]}    5
+     Should Be Equal As Integers    ${result[1]}    ${docker_number}
      Sleep  2s
 
-Start Redis
-     Run And Return Rc And Output    ${redis_remove}
-     Run And Return Rc And Output    ${start_redis}
+Start Dbass
+     Run And Return Rc And Output    ${dbass_remove}
+     Run And Return Rc And Output    ${dbass_start}
+     ${result}=  Run And Return Rc And Output     ${docker_command}
+     Should Be Equal As Integers    ${result[1]}    ${docker_number}
+
+Stop Dbass
+     Run And Return Rc And Output    ${dbass_stop}
      ${result}=  Run And Return Rc And Output     ${docker_command}
-     Should Be Equal As Integers    ${result[1]}    5
+     Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
 
 
 
diff --git a/Automation/Tests/Resource/config.py b/Automation/Tests/Resource/config.py
deleted file mode 100644 (file)
index b608bee..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-##############################################################################
-#
-#   Copyright (c) 2019 AT&T Intellectual Property.
-#
-#   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.
-#
-##############################################################################
-
-redis_ip_address = 'localhost'
-redis_ip_port = 6379
index 118ca24..3fdee76 100755 (executable)
@@ -21,29 +21,46 @@ Documentation    Resource file
 
 
 *** Variables ***
+${docker_number}    6
+${docker_number-1}    5
+${ip_gnb_simu} 10.0.2.15
+${ip_e2adapter}        10.0.2.15
 ${url}   http://localhost:3800
 ${json}    {"ranIp": "10.0.2.15","ranPort": 5577,"ranName":"test1"}
+${endcbadjson}    {"ranIp": "a","ranPort": 49999,"ranName":"test2"}
 ${endcjson}    {"ranIp": "10.0.2.15","ranPort": 49999,"ranName":"test2"}
 ${resetcausejson}   {"cause": "misc:not-enough-user-plane-processing-resources"}
+${resetbadcausejson}   {"cause": "bla" }
+${resetbad1causejson}   {"cause":  }
 ${header}  {"Content-Type": "application/json"}
 ${docker_command}  docker ps | grep Up | wc --lines
 ${run_simu_load}   docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422  --env duration=600000000000 --env indicationReportRate=1000000000 --env indicationInsertRate=0 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.6
+#${run_simu_load}   docker run -d --name gnbe2_simu  -h gnb-sim --env gNBipv4=gnb-sim  --env gNBport=5577/sctp  --env duration=600000000000 --env indicationReportRate=1000000000 --env indicationInsertRate=0 snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.6
 ${stop_simu}  docker stop gnbe2_simu
 ${run_simu_regular}  docker run -d --name gnbe2_simu --env gNBipv4=localhost  --env gNBport=36422 --env duration=600000000000 --env indicationReportRate=0 --env indicationInsertRate=0 -p 5577:36422/sctp snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.6
+#${run_simu_regular}  docker run -d --name gnbe2_simu  -h gnb-sim --env gNBipv4=gnb-sim  --env gNBport=5577/sctp --env duration=600000000000 --env indicationReportRate=0 --env indicationInsertRate=0  snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/gnbe2_simu:1.0.6
 ${docker_Remove}    docker rm gnbe2_simu
 ${docker_restart}   docker restart e2mgr
 ${restart_simu}  docker restart gnbe2_simu
 ${restart_e2adapter}  docker restart e2adapter
 ${start_e2}  docker start e2
 ${stop_docker_e2}      docker stop e2
-${start_redis}   docker run -d --name redis -p 6379:6379 --env DBAAS_SERVICE_HOST=10.0.2.15  snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/dbass:1.0.0
-${redis_remove}    docker rm redis
+${dbass_start}   docker run -d --name dbass -p 6379:6379 --env DBAAS_SERVICE_HOST=10.0.2.15  snapshot.docker.ranco-dev-tools.eastus.cloudapp.azure.com:10001/dbass:1.0.0
+${dbass_remove}    docker rm dbass
+${dbass_stop}      docker stop dbass
 ${restart_simu}  docker restart gnbe2_simu
 ${start_e2}  docker start e2
 ${stop_docker_e2}      docker stop e2
 ${Run_Config}       docker exec gnbe2_simu pkill gnbe2_simu -INT
-${Save_e2_log}      docker logs gnbe2_simu > gnb.log
+${Save_sim_log}      docker logs gnbe2_simu > gnb.log
 ${Save_e2mgr_log}   docker logs e2mgr > e2mgr.log
+${Save_rsm_log}   docker logs rsm > rsm.log
+${Save_e2adapter_log}   docker logs e2adapter > e2adapter.log
+${403_reset_message}    "Activity X2_RESET rejected. RAN current state DISCONNECTED does not allow its execution "
+${e2mgr_log_filename}    e2mgr.log
+${gnb_log_filename}    gnb.log
+${rsm_log_filename}    rsm.log
+${e2adapter_log_filename}    e2adapter.log
 
 
 
diff --git a/Automation/Tests/Resource/scripts_variables.robot b/Automation/Tests/Resource/scripts_variables.robot
new file mode 100644 (file)
index 0000000..4839304
--- /dev/null
@@ -0,0 +1,39 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Documentation    Message types resource file
+
+
+*** Variables ***
+${configurationupdate_message_type}    MType: 10370
+${Meid_test1}   Meid: \\"test1\\"
+${Meid_test2}   Meid: \\"test2\\"
+${configurationupdate_ack_message_type}    MType: 10371
+${RAN_CONNECTED_message_type}     MType: 1200
+${RAN_RESTARTED_message_type}     MType: 1210
+${RIC_X2_RESET_REQ_message_type}    MType: 10070
+${RIC_X2_RESET_RESP_message_type}    MType: 10070
+${failed_to_retrieve_nodeb_message}     failed to retrieve nodeB entity. RanName: test1.
+${first_retry_to_retrieve_from_db}      RnibDataService.retry - retrying 1 GetNodeb
+${third_retry_to_retrieve_from_db}      RnibDataService.retry - after 3 attempts of GetNodeb
+${RIC_RES_STATUS_REQ_message_type_successfully_sent}     Message type: 10090 - Successfully sent RMR message
+${RAN_NAME_test1}    RAN name: test1
+${RAN_NAME_test2}    RAN name: test2
+${E2ADAPTER_Setup_Resp}    Send dummy ENDCX2SetupResponse to RIC
+
old mode 100755 (executable)
new mode 100644 (file)
similarity index 100%
rename from Automation/Tests/Get-All-Nodes/config.py
rename to Automation/Tests/Scripts/config.py
diff --git a/Automation/Tests/Scripts/find_error_script.py b/Automation/Tests/Scripts/find_error_script.py
new file mode 100644 (file)
index 0000000..d780a58
--- /dev/null
@@ -0,0 +1,36 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+
+def find_error(directory,filename, message):
+
+    path = '/'
+
+    file_path = directory + path + filename
+
+    f = open(file_path, 'r')
+
+    for l in f:
+
+        if l.find(message) > 0:
+            return True
+
+    return False
+
+
+
diff --git a/Automation/Tests/Scripts/find_rmr_message.py b/Automation/Tests/Scripts/find_rmr_message.py
new file mode 100644 (file)
index 0000000..1d75e81
--- /dev/null
@@ -0,0 +1,35 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+
+def verify_logs(directory,filename,mtype,meid):
+
+    path = '/'
+
+    file_path = directory + path + filename
+
+    f = open(file_path, 'r')
+
+    for l in f:
+
+        if l.find(mtype) > 0 and l.find(meid) > 0:
+            return True
+
+    return False
+
+
diff --git a/Automation/Tests/Unhappy/Get_All_Nodedb_HttpResponse500.robot b/Automation/Tests/Unhappy/Get_All_Nodedb_HttpResponse500.robot
new file mode 100644 (file)
index 0000000..f10ce63
--- /dev/null
@@ -0,0 +1,34 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/resource.robot
+Library     REST      ${url}
+Suite Teardown   Start Dbass
+
+*** Test Cases ***
+ENDC-setup - 500 http - 500 RNIB error
+    Stop Dbass
+    GET      /v1/nodeb/ids
+    Integer  response status            500
+    Integer  response body errorCode            500
+    String   response body errorMessage     RNIB error
+
+
diff --git a/Automation/Tests/Unhappy/Get_Nodeb_HttpResponse500.robot b/Automation/Tests/Unhappy/Get_Nodeb_HttpResponse500.robot
new file mode 100644 (file)
index 0000000..e930989
--- /dev/null
@@ -0,0 +1,49 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource    ../Resource/scripts_variables.robot
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/resource.robot
+Library    ../Scripts/find_error_script.py
+Library     OperatingSystem
+Library     REST      ${url}
+Suite Teardown   Start Dbass
+
+*** Test Cases ***
+Get node b gnb - DB down - 500
+    Stop Dbass
+    GET      /v1/nodeb/test5
+    Integer  response status            500
+    Integer  response body errorCode            500
+    String   response body errorMessage     RNIB error
+
+
+Prepare logs for tests
+    Remove log files
+    Save logs
+
+Verify e2mgr logs - First retry to retrieve from db
+  ${result}    find_error_script.find_error     ${EXECDIR}  ${e2mgr_log_filename}    ${first_retry_to_retrieve_from_db}
+   Should Be Equal As Strings    ${result}      True
+
+Verify e2mgr logs - Third retry to retrieve from db
+   ${result}    find_error_script.find_error     ${EXECDIR}  ${e2mgr_log_filename}   ${third_retry_to_retrieve_from_db}
+   Should Be Equal As Strings    ${result}      True
+
diff --git a/Automation/Tests/Unhappy/RedButton_HttpResponse500.robot b/Automation/Tests/Unhappy/RedButton_HttpResponse500.robot
new file mode 100644 (file)
index 0000000..7950a36
--- /dev/null
@@ -0,0 +1,34 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/resource.robot
+Library     REST      ${url}
+Suite Teardown   Start Dbass
+
+*** Test Cases ***
+Red Button - Shut Dwon - 500 RNIB error
+    Stop Dbass
+    PUT      /v1/nodeb/shutdown
+    Integer  response status            500
+    Integer  response body errorCode            500
+    String   response body errorMessage     RNIB error
+
+
 
 *** Settings ***
 Suite Setup   Prepare Enviorment
-Resource   ../Resource/resource.robot
+Library     Collections
 Resource   ../Resource/Keywords.robot
+Resource   ../Resource/resource.robot
 Library     OperatingSystem
-Library     Collections
 Library     REST      ${url}
 
 
@@ -29,28 +29,26 @@ Library     REST      ${url}
 
 
 *** Test Cases ***
-
-Prepare Ran in Connected connectionStatus
+Reset - 400 http - 401 Corrupted json
     Post Request setup node b x-2
     Integer     response status       204
     Sleep  1s
     GET      /v1/nodeb/test1
-    Integer  response status  200
-    String   response body ranName    test1
     String   response body connectionStatus    CONNECTED
+    Set Headers     ${header}
+    PUT    /v1/nodeb/test1/reset  {abc}
+    Integer    response status   400
+    Integer    response body errorCode  401
+    String     response body errorMessage  corrupted json
+
+Reset - 400 http - 401 Validation error
+    Set Headers     ${header}
+    PUT    /v1/nodeb/test1/reset    ${resetbadcausejson}
+    Integer    response status   400
+    Integer    response body errorCode  402
+    String     response body errorMessage  Validation error
+
 
-Stop RNIB
-      Run   docker stop redis
 
-Run Reset from RAN
-    Run    ${Run_Config}
-    Sleep   1s
 
-Remove log files
-    Remove File  ${EXECDIR}/gnb.log
-    Remove File  ${EXECDIR}/e2mgr.log
 
-Save logs
-    Sleep   1s
-    Run     ${Save_e2_log}
-    Run     ${Save_e2mgr_log}
\ No newline at end of file
diff --git a/Automation/Tests/Unhappy/Reset_HttpResponse400_wrongstate.robot b/Automation/Tests/Unhappy/Reset_HttpResponse400_wrongstate.robot
new file mode 100644 (file)
index 0000000..f08eb73
--- /dev/null
@@ -0,0 +1,53 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Library     Collections
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/resource.robot
+Library     OperatingSystem
+Library     REST      ${url}
+
+
+
+
+
+*** Test Cases ***
+
+Pre Condition for Connecting - no simu
+    Run And Return Rc And Output    ${stop_simu}
+    ${result}=  Run And Return Rc And Output     ${docker_command}
+    Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
+
+Reset - 400 http - 403 wrong state
+    Post Request setup node b x-2
+    Integer     response status       204
+    Sleep  1s
+    GET      /v1/nodeb/test1
+    String   response body connectionStatus    DISCONNECTED
+    Set Headers     ${header}
+    PUT    /v1/nodeb/test1/reset
+    #Output
+    Integer    response status   400
+    Integer    response body errorCode  403
+    String     response body errorMessage   ${403_reset_message}
+
+
+
+
old mode 100755 (executable)
new mode 100644 (file)
similarity index 82%
rename from Automation/Tests/Unhappy/Response400.robot
rename to Automation/Tests/Unhappy/Reset_HttpResponse404.robot
index e4262e4..eaceb1c
@@ -24,10 +24,11 @@ Library     OperatingSystem
 Library     REST      ${url}
 
 
-
 *** Test Cases ***
-Post Request setup node b endc-setup - 400 validation of fields
+Reset - 404 http - 404 Corrupted json
     Set Headers     ${header}
-    POST        /v1/nodeb/endc-setup
-    Integer    response status   400
+    PUT    /v1/nodeb/test11/reset
+    Integer    response status   404
+    Integer    response body errorCode  404
+    String     response body errorMessage  Resource not found
 
diff --git a/Automation/Tests/Unhappy/Setup_Request_HttpResponse400.robot b/Automation/Tests/Unhappy/Setup_Request_HttpResponse400.robot
new file mode 100644 (file)
index 0000000..a98d7d7
--- /dev/null
@@ -0,0 +1,47 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Library     Collections
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/resource.robot
+Library     OperatingSystem
+Library     REST      ${url}
+
+
+
+*** Test Cases ***
+Endc-setup - 400 http - 401 Corrupted json
+    Set Headers     ${header}
+    POST        /v1/nodeb/endc-setup
+    Integer    response status   400
+    Integer    response body errorCode  401
+    String     response body errorMessage  corrupted json
+
+Endc-setup - 400 http - 402 Validation error
+    Set Headers     ${header}
+    POST        /v1/nodeb/endc-setup     ${endcbadjson}
+    Integer    response status   400
+    Integer    response body errorCode  402
+    String     response body errorMessage  Validation error
+
+
+
+
+
diff --git a/Automation/Tests/Unhappy/Setup_Request_HttpResponse500.robot b/Automation/Tests/Unhappy/Setup_Request_HttpResponse500.robot
new file mode 100644 (file)
index 0000000..82a2c2d
--- /dev/null
@@ -0,0 +1,35 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/Keywords.robot
+Resource   ../Resource/resource.robot
+Library     REST      ${url}
+Suite Teardown   Start Dbass
+
+*** Test Cases ***
+ENDC-setup - 500 http - 500 RNIB error
+    Stop Dbass
+    Set Headers     ${header}
+    POST     /v1/nodeb/endc-setup    ${json}
+    Integer  response status            500
+    Integer  response body errorCode            500
+    String   response body errorMessage     RNIB error
+
+
old mode 100755 (executable)
new mode 100644 (file)
similarity index 94%
rename from Automation/Tests/Unhappy/Setup_failure.robot
rename to Automation/Tests/Unhappy/Setup_Request_setup_failure.robot
index a53abd1..fb93b2f
@@ -37,6 +37,6 @@ Post Request setup node b x2-setup - setup failure
     Integer    response status       200
     String     response body connectionStatus     CONNECTED_SETUP_FAILED
     String     response body failureType     X2_SETUP_FAILURE
-    String     response body setupFailure networkLayerCause       HO_TARGET_NOT_ALLOWED
+
 
 
index 477cb63..f17bcc7 100755 (executable)
@@ -20,7 +20,9 @@
 Suite Setup   Prepare Enviorment
 Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
+Resource    ../Resource/scripts_variables.robot
 Library     OperatingSystem
+Library     ../Scripts/find_rmr_message.py
 Library     REST      ${url}
 
 *** Test Cases ***
@@ -32,7 +34,7 @@ X2 - Get Nodeb
     Get Request Node B Enb test1
     Integer  response status  200
     String   response body ranName    test1
-    String   response body ip    10.0.2.15
+    String   response body ip    ${ip_gnb_simu} 
     Integer  response body port     5577
     String   response body connectionStatus    CONNECTED
     String   response body nodeType     ENB
@@ -47,6 +49,16 @@ X2 - Get Nodeb
     String   response body enb servedCells 0 choiceEutraMode fdd dlTransmissionBandwidth   BW50
 
 
+prepare logs for tests
+    Remove log files
+    Save logs
 
 
+X2 - RAN Connected message going to be sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}   ${e2mgr_log_filename}  ${RAN_CONNECTED_message_type}    ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
 
@@ -42,11 +42,7 @@ Run Reset from RAN
     Run    ${Run_Config}
     Sleep   1s
 
-Remove log files
-    Remove File  ${EXECDIR}/gnb.log
-    Remove File  ${EXECDIR}/e2mgr.log
+Prepare logs for tests
+    Remove log files
+    Save logs
 
-Save logs
-    Sleep   1s
-    Run     ${Save_e2_log}
-    Run     ${Save_e2mgr_log}
\ No newline at end of file
 
 
 *** Settings ***
+Resource    ../Resource/scripts_variables.robot
+Resource   ../Resource/Keywords.robot
 Library     String
 Library     OperatingSystem
 Library     Process
-Library     ${CURDIR}/Reset_Ran_To_Ric_Verify_logs.py
+Library     ../Scripts/find_rmr_message.py
+
 
 
 *** Test Cases ***
 Verify logs - Reset Sent by simulator
     ${Reset}=   Grep File  ./gnb.log  ResetRequest has been sent
-    #Log to console      ${Reset}
     Should Be Equal     ${Reset}     gnbe2_simu: ResetRequest has been sent
 
-Verify logs - e2mgr logs
-   ${result}    Reset_Ran_To_Ric_Verify_logs.verify   ${EXECDIR}
-   Should Be Equal As Strings    ${result}      True
\ No newline at end of file
+Verify logs - e2mgr logs - messege sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+Verify logs - e2mgr logs - messege received
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_RESP_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RAN Restarted messege sent
+    ${result}    find_rmr_message.verify_logs  ${EXECDIR}  ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}  ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
@@ -17,4 +17,4 @@
 ##############################################################################
 
 *** Settings ***
-Documentation    ORAN Reset - RAN to RIC Scenario 2
+Documentation    ORAN Reset - X2 RAN to RIC Scenario 1
old mode 100755 (executable)
new mode 100644 (file)
similarity index 87%
rename from Automation/Tests/Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot
rename to Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/Reset_RNIB.robot
index 20e4258..13ef687
@@ -17,7 +17,7 @@
 ##############################################################################
 
 *** Settings ***
-Suite Setup  Prepare Enviorment
+Suite Setup   Prepare Enviorment
 Resource   ../Resource/resource.robot
 Resource   ../Resource/Keywords.robot
 Library     OperatingSystem
@@ -25,7 +25,11 @@ Library     Collections
 Library     REST      ${url}
 
 
+
+
+
 *** Test Cases ***
+
 Prepare Ran in Connected connectionStatus
     Post Request setup node b x-2
     Integer     response status       204
@@ -35,8 +39,15 @@ Prepare Ran in Connected connectionStatus
     String   response body ranName    test1
     String   response body connectionStatus    CONNECTED
 
+Stop RNIB
+    Stop Dbass
+
+
+Run Reset from RAN
+    Run    ${Run_Config}
+    Sleep   1s
+
+Prepare logs for tests
+    Remove log files
+    Save logs
 
-Send Reset reqeust with no cause
-    Set Headers     ${header}
-    PUT    /v1/nodeb/test1/reset
-    Integer  response status  204
\ No newline at end of file
 
 
 *** Settings ***
+Resource    ../Resource/scripts_variables.robot
 Library     String
 Library     OperatingSystem
 Library     Process
-Library     ${CURDIR}/Reset_Ran_To_Ric_RNIB_Down_Verify_logs.py
 Resource   ../Resource/Keywords.robot
-Test Teardown  Start Redis with 4 dockers
+Library     ../Scripts/find_rmr_message.py
+Library     ../Scripts/find_error_script.py
+Test Teardown  Start Dbass with 4 dockers
 
 
 
 *** Test Cases ***
 Verify logs - Reset Sent by simulator
     ${Reset}=   Grep File  ./gnb.log  ResetRequest has been sent
-    #Log to console      ${Reset}
     Should Be Equal     ${Reset}     gnbe2_simu: ResetRequest has been sent
 
-Verify logs - e2mgr logs
-   ${result}    Reset_Ran_To_Ric_RNIB_Down_Verify_logs.verify   ${EXECDIR}
-   log to console   ${result}
-   Should Be Equal As Strings    ${result}      True
+Verify logs for restart received
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}  ${e2mgr_log_filename}  ${RIC_X2_RESET_REQ_message_type}    ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+Verify for error on retrying
+    ${result}    find_error_script.find_error    ${EXECDIR}     ${e2mgr_log_filename}   ${failed_to_retrieve_nodeb_message}
+    Should Be Equal As Strings    ${result}      True
 
 
 *** Keywords ***
-Start Redis with 4 dockers
-     Run And Return Rc And Output    ${redis_remove}
-     Run And Return Rc And Output    ${start_redis}
+Start Dbass with 4 dockers
+     Run And Return Rc And Output    ${dbass_remove}
+     Run And Return Rc And Output    ${dbass_start}
      ${result}=  Run And Return Rc And Output     ${docker_command}
-     Should Be Equal As Integers    ${result[1]}    4
+     Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
      Sleep  5s
diff --git a/Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/__init__.robot b/Automation/Tests/X2_Reset_RAN_TO_RIC_Unhappy/__init__.robot
new file mode 100644 (file)
index 0000000..724f2ff
--- /dev/null
@@ -0,0 +1,20 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Documentation    ORAN Reset - RAN to RIC Scenario Unhappy
diff --git a/Automation/Tests/X2_Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot b/Automation/Tests/X2_Reset_RIC_TO_RAN/Reset_Happy_no_cause.robot
new file mode 100644 (file)
index 0000000..41db2b8
--- /dev/null
@@ -0,0 +1,56 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource    ../Resource/scripts_variables.robot
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Library     OperatingSystem
+Library     ../Scripts/find_rmr_message.py
+Library     REST      ${url}
+
+
+*** Test Cases ***
+Prepare Ran in Connected connectionStatus
+    Post Request setup node b x-2
+    Integer     response status       204
+    Sleep  1s
+    GET      /v1/nodeb/test1
+    Integer  response status  200
+    String   response body ranName    test1
+    String   response body connectionStatus    CONNECTED
+
+
+Send Reset reqeust with no cause
+    Set Headers     ${header}
+    PUT    /v1/nodeb/test1/reset
+    Integer  response status  204
+
+Prepare logs for tests
+    Remove log files
+    Save logs
+
+
+RAN Restarted messege sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}    ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
diff --git a/Automation/Tests/X2_Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot b/Automation/Tests/X2_Reset_RIC_TO_RAN/Reset_Happy_with_cause.robot
new file mode 100644 (file)
index 0000000..cfec18c
--- /dev/null
@@ -0,0 +1,57 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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.
+#
+##############################################################################
+
+*** Settings ***
+Suite Setup  Prepare Enviorment
+Resource    ../Resource/scripts_variables.robot
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Library     OperatingSystem
+Library     ../Scripts/find_rmr_message.py
+Library     REST      ${url}
+
+
+*** Test Cases ***
+Prepare Ran in Connected connectionStatus
+    Post Request setup node b x-2
+    Integer     response status       204
+    Sleep  1s
+    GET      /v1/nodeb/test1
+    Integer  response status  200
+    String   response body ranName    test1
+    String   response body connectionStatus    CONNECTED
+
+
+Send Reset reqeust with cause
+    Set Headers     ${header}
+    PUT    /v1/nodeb/test1/reset    ${resetcausejson}
+    Integer  response status  204
+
+
+Prepare logs for tests
+    Remove log files
+    Save logs
+
+
+RAN Restarted messege sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${e2mgr_log_filename}  ${RAN_RESTARTED_message_type}    ${Meid_test1}
+    Should Be Equal As Strings    ${result}      True
+
+RSM RESOURCE STATUS REQUEST message sent
+    ${result}    find_rmr_message.verify_logs     ${EXECDIR}    ${rsm_log_filename}  ${RIC_RES_STATUS_REQ_message_type_successfully_sent}    ${RAN_NAME_test1}
+    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
old mode 100755 (executable)
new mode 100644 (file)
similarity index 94%
rename from Automation/Tests/Reset_RIC_TO_RAN/__init__.robot
rename to Automation/Tests/X2_Reset_RIC_TO_RAN/__init__.robot
index 0e9f050..0627161
@@ -17,4 +17,4 @@
 ##############################################################################
 
 *** Settings ***
-Documentation    ORAN Reset API - RIC to RAN
+Documentation    ORAN Reset API - X2 RIC to RAN
index b1449a4..44ff59e 100644 (file)
@@ -23,20 +23,36 @@ COPY . .
 ENV PATH=$PATH:/usr/local/go/bin:/usr/lib/go-1.12/bin
 #RUN git clone https://gerrit.o-ran-sc.org/r/ric-plt/lib/rmr && cd rmr/; mkdir build; cd build; /opt/bin/cmake -DDEV_PKG=1 ..; make install
 # Install RMr library and dev files
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/master/packages/debian/stretch/rmr_1.3.0_amd64.deb/download.deb
-RUN dpkg -i rmr_1.3.0_amd64.deb
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/master/packages/debian/stretch/rmr-dev_1.3.0_amd64.deb/download.deb
-RUN dpkg -i rmr-dev_1.3.0_amd64.deb
-
+RUN wget --content-disposition  https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.10.0_amd64.deb/download.deb
+RUN dpkg -i rmr_1.10.0_amd64.deb
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr-dev_1.10.0_amd64.deb/download.deb
+RUN dpkg -i rmr-dev_1.10.0_amd64.deb
 
 RUN cd asn1codec && make  
-RUN go build main/http_server.go 
+RUN go build app/main.go
 
+# Execute UT
+ENV LD_LIBRARY_PATH=/usr/local/lib
 
+# cgocheck=2 enables expensive checks that should not miss any errors, but will cause your program to run slower.
+# clobberfree=1 causes the garbage collector to clobber the memory content of an object with bad content when it frees the object.
+# gcstoptheworld=1 disables concurrent garbage collection, making every garbage collection a stop-the-world event.
+# Setting gcstoptheworld=2 also disables concurrent sweeping after the garbage collection finishes.
+# Setting allocfreetrace=1 causes every allocation to be profiled and a stack trace printed on each object's allocation and free.
+ENV GODEBUG=cgocheck=2,clobberfree=1,gcstoptheworld=2,allocfreetrace=0
+ENV RIC_ID="bbbccc-abcd0e/20"
+RUN go test ./...
 
 FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y \
+  net-tools \
+  iputils-ping \
+  curl \
+  tcpdump
+  
 COPY --from=ubuntu /opt/E2Manager/router.txt /opt/E2Manager/router.txt
-COPY --from=ubuntu /opt/E2Manager/http_server /opt/E2Manager/http_server
+COPY --from=ubuntu /opt/E2Manager/main /opt/E2Manager/main
 COPY --from=ubuntu /opt/E2Manager/resources /opt/E2Manager/resources
 COPY --from=ubuntu /usr/local/lib/librmr_nng.so.1 /usr/local/lib/librmr_nng.so.1
 COPY --from=ubuntu /usr/local/lib/libnng.so.1 /usr/local/lib/libnng.so.1
@@ -45,4 +61,4 @@ ENV LD_LIBRARY_PATH=/usr/local/lib \
     port=3800 
 ENV RMR_SEED_RT=router.txt
 EXPOSE 3800
-CMD ["sh", "-c", "./http_server  -port=$port"]
+CMD ["sh", "-c", "./main  -port=$port"]
diff --git a/E2Manager/app/main.go b/E2Manager/app/main.go
new file mode 100644 (file)
index 0000000..ce41eeb
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package main
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/controllers"
+       "e2mgr/converters"
+       "e2mgr/httpserver"
+       "e2mgr/logger"
+       "e2mgr/managers"
+       "e2mgr/managers/notificationmanager"
+       "e2mgr/providers/httpmsghandlerprovider"
+       "e2mgr/providers/rmrmsghandlerprovider"
+       "e2mgr/rNibWriter"
+       "e2mgr/rmrCgo"
+       "e2mgr/services"
+       "e2mgr/services/rmrreceiver"
+       "e2mgr/services/rmrsender"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
+       "os"
+       "strconv"
+)
+
+const MAX_RNIB_POOL_INSTANCES = 4
+
+func main() {
+       config := configuration.ParseConfiguration()
+       logLevel, _ := logger.LogLevelTokenToLevel(config.Logging.LogLevel)
+       logger, err := logger.InitLogger(logLevel)
+       if err != nil {
+               fmt.Printf("#app.main - failed to initialize logger, error: %s", err)
+               os.Exit(1)
+       }
+       rNibWriter.Init("e2Manager", MAX_RNIB_POOL_INSTANCES)
+       defer rNibWriter.Close()
+       reader.Init("e2Manager", MAX_RNIB_POOL_INSTANCES)
+       defer reader.Close()
+       rnibDataService := services.NewRnibDataService(logger, config, reader.GetRNibReader, rNibWriter.GetRNibWriter)
+       var msgImpl *rmrCgo.Context
+       rmrMessenger := msgImpl.Init("tcp:"+strconv.Itoa(config.Rmr.Port), config.Rmr.MaxMsgSize, 0, logger)
+       rmrSender := rmrsender.NewRmrSender(logger, rmrMessenger)
+       ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
+       ranReconnectionManager := managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager)
+       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
+       x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
+       x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter)
+       x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
+       x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
+       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager)
+
+       notificationManager := notificationmanager.NewNotificationManager(logger, rmrNotificationHandlerProvider)
+       rmrReceiver := rmrreceiver.NewRmrReceiver(logger, rmrMessenger, notificationManager)
+
+       defer (*rmrMessenger).Close()
+
+       go rmrReceiver.ListenAndHandle()
+
+       httpMsgHandlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrSender, config, rnibDataService, ranSetupManager)
+       rootController := controllers.NewRootController(rnibDataService)
+       nodebController := controllers.NewNodebController(logger, httpMsgHandlerProvider)
+       httpserver.Run(config.Http.Port, rootController, nodebController)
+}
index 7d8992a..cfba4d2 100644 (file)
@@ -49,7 +49,7 @@ func ParseConfiguration() *Configuration{
        viper.AddConfigPath("../../resources/") //For test under Docker
        err := viper.ReadInConfig()
        if err != nil {
-               panic(fmt.Sprintf("#http_server.parseConfiguration - failed to read configuration file: %s\n", err))
+               panic(fmt.Sprintf("#configuration.ParseConfiguration - failed to read configuration file: %s\n", err))
        }
 
        config := Configuration{}
@@ -60,28 +60,28 @@ func ParseConfiguration() *Configuration{
        config.NotificationResponseBuffer = viper.GetInt("notificationResponseBuffer")
        config.BigRedButtonTimeoutSec = viper.GetInt("bigRedButtonTimeoutSec")
        config.MaxConnectionAttempts = viper.GetInt("maxConnectionAttempts")
-       config.MaxConnectionAttempts = viper.GetInt("maxRnibConnectionAttempts")
-       config.MaxConnectionAttempts = viper.GetInt("rnibRetryIntervalMs")
+       config.MaxRnibConnectionAttempts = viper.GetInt("maxRnibConnectionAttempts")
+       config.RnibRetryIntervalMs = viper.GetInt("rnibRetryIntervalMs")
        return &config
 }
 
 func (c *Configuration)fillLoggingConfig(logConfig *viper.Viper) {
        if logConfig == nil {
-               panic(fmt.Sprintf("#http_server.fillLoggingConfig - failed to fill logging configuration: The entry 'logging' not found\n"))
+               panic(fmt.Sprintf("#configuration.fillLoggingConfig - failed to fill logging configuration: The entry 'logging' not found\n"))
        }
        c.Logging.LogLevel = logConfig.GetString("logLevel")
 }
 
 func (c *Configuration)fillHttpConfig(httpConfig *viper.Viper) {
        if httpConfig == nil {
-               panic(fmt.Sprintf("#http_server.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n"))
+               panic(fmt.Sprintf("#configuration.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n"))
        }
        c.Http.Port = httpConfig.GetInt("port")
 }
 
 func (c *Configuration)fillRmrConfig(rmrConfig *viper.Viper) {
        if rmrConfig == nil {
-               panic(fmt.Sprintf("#http_server.fillRmrConfig - failed to fill RMR configuration: The entry 'rmr' not found\n"))
+               panic(fmt.Sprintf("#configuration.fillRmrConfig - failed to fill RMR configuration: The entry 'rmr' not found\n"))
        }
        c.Rmr.Port = rmrConfig.GetInt("port")
        c.Rmr.MaxMsgSize = rmrConfig.GetInt("maxMsgSize")
diff --git a/E2Manager/configuration/configuration_test.go b/E2Manager/configuration/configuration_test.go
new file mode 100644 (file)
index 0000000..370e79e
--- /dev/null
@@ -0,0 +1,138 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package configuration
+
+import (
+       "github.com/stretchr/testify/assert"
+       "gopkg.in/yaml.v2"
+       "io/ioutil"
+       "os"
+       "testing"
+)
+
+func TestParseConfigurationSuccess(t *testing.T) {
+       config := ParseConfiguration()
+       assert.Equal(t, 3800, config.Http.Port)
+       assert.Equal(t, 3801, config.Rmr.Port)
+       assert.Equal(t, 65536, config.Rmr.MaxMsgSize)
+       assert.Equal(t, "info", config.Logging.LogLevel)
+       assert.Equal(t, 100, config.NotificationResponseBuffer)
+       assert.Equal(t, 5, config.BigRedButtonTimeoutSec)
+}
+
+func TestParseConfigurationFileNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestParseConfigurationFileNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestParseConfigurationFileNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       assert.Panics(t, func() { ParseConfiguration() })
+}
+
+func TestRmrConfigNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestRmrConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestRmrConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       yamlMap := map[string]interface{}{
+               "logging": map[string]interface{}{"logLevel": "info"},
+               "http":    map[string]interface{}{"port": 3800},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestRmrConfigNotFoundFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestRmrConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.fillRmrConfig - failed to fill RMR configuration: The entry 'rmr' not found\n", func() { ParseConfiguration() })
+}
+
+func TestLoggingConfigNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestLoggingConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestLoggingConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       yamlMap := map[string]interface{}{
+               "rmr":  map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
+               "http": map[string]interface{}{"port": 3800},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestRmrConfigNotFoundFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestRmrConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.fillLoggingConfig - failed to fill logging configuration: The entry 'logging' not found\n",
+               func() { ParseConfiguration() })
+}
+
+func TestHttpConfigNotFoundFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestHttpConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               }
+       }()
+       yamlMap := map[string]interface{}{
+               "rmr":     map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
+               "logging": map[string]interface{}{"logLevel": "info"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestHttpConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n",
+               func() { ParseConfiguration() })
+}
index bad22ad..e22b9c2 100644 (file)
@@ -1,4 +1,4 @@
 # The Jenkins job requires a tag to build the Docker image.
 # Global-JJB script assumes this file is in the repo root.
 ---
-tag: 2.0.5
+tag: 2.0.7
diff --git a/E2Manager/controllers/controller.go b/E2Manager/controllers/controller.go
deleted file mode 100644 (file)
index 12ade63..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// 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.
-//
-
-package controllers
-
-import (
-       "e2mgr/configuration"
-       "e2mgr/e2managererrors"
-       "e2mgr/logger"
-       "e2mgr/managers"
-       "e2mgr/models"
-       "e2mgr/providers/httpmsghandlerprovider"
-       "e2mgr/services"
-       "encoding/json"
-       "github.com/gorilla/mux"
-       "io"
-       "io/ioutil"
-       "net/http"
-       "net/http/httputil"
-       "strings"
-)
-
-const (
-       ParamRanName = "ranName"
-       LimitRequest = 2000
-)
-
-type IController interface {
-       ShutdownHandler(writer http.ResponseWriter, r *http.Request)
-       X2ResetHandler(writer http.ResponseWriter, r *http.Request)
-       X2SetupHandler(writer http.ResponseWriter, r *http.Request)
-       EndcSetupHandler(writer http.ResponseWriter, r *http.Request)
-}
-
-type Controller struct {
-       logger          *logger.Logger
-       handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider
-}
-
-func NewController(logger *logger.Logger, rmrService *services.RmrService, rnibDataService services.RNibDataService,
-       config *configuration.Configuration, ranSetupManager *managers.RanSetupManager) *Controller {
-
-       provider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrService, config, rnibDataService, ranSetupManager)
-       return &Controller{
-               logger:          logger,
-               handlerProvider: provider,
-       }
-}
-
-func (c *Controller) ShutdownHandler(writer http.ResponseWriter, r *http.Request) {
-       c.logger.Infof("[Client -> E2 Manager] #controller.ShutdownHandler - request: %v", c.prettifyRequest(r))
-       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ShutdownRequest, nil, false)
-}
-
-func (c *Controller) X2ResetHandler(writer http.ResponseWriter, r *http.Request) {
-       c.logger.Infof("[Client -> E2 Manager] #controller.X2ResetHandler - request: %v", c.prettifyRequest(r))
-       request := models.ResetRequest{}
-       vars := mux.Vars(r)
-       ranName := vars[ParamRanName]
-
-       if r.ContentLength > 0 && !c.extractJsonBody(r, &request, writer) {
-               return
-       }
-       request.RanName = ranName
-       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ResetRequest, request, false)
-}
-
-func (c *Controller) X2SetupHandler(writer http.ResponseWriter, r *http.Request) {
-       c.logger.Infof("[Client -> E2 Manager] #controller.X2SetupHandler - request: %v", c.prettifyRequest(r))
-
-       request := models.SetupRequest{}
-
-       if !c.extractJsonBody(r, &request, writer) {
-               return
-       }
-
-       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.X2SetupRequest, request, true)
-}
-
-func (c *Controller) EndcSetupHandler(writer http.ResponseWriter, r *http.Request) {
-       c.logger.Infof("[Client -> E2 Manager] #controller.EndcSetupHandler - request: %v", c.prettifyRequest(r))
-
-       request := models.SetupRequest{}
-
-       if !c.extractJsonBody(r, &request, writer) {
-               return
-       }
-
-       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.EndcSetupRequest, request, true)
-}
-
-func (c *Controller) extractJsonBody(r *http.Request, request models.Request, writer http.ResponseWriter) bool {
-       defer r.Body.Close()
-       body, err := ioutil.ReadAll(io.LimitReader(r.Body, LimitRequest))
-
-       if err != nil {
-               c.logger.Errorf("[Client -> E2 Manager] #controller.extractJsonBody - unable to extract json body - error: %s", err)
-               c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
-               return false
-       }
-
-       err = json.Unmarshal(body, &request)
-       if err != nil {
-               c.logger.Errorf("[Client -> E2 Manager] #controller.extractJsonBody - unable to extract json body - error: %s", err)
-               c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
-               return false
-       }
-
-       return true
-}
-
-func (c *Controller) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest,
-       request models.Request, validateHeader bool) {
-
-       if validateHeader {
-
-               err := c.validateRequestHeader(header)
-               if err != nil {
-                       c.handleErrorResponse(err, writer)
-                       return
-               }
-       }
-
-       handler, err := c.handlerProvider.GetHandler(requestName)
-
-       if err != nil {
-               c.handleErrorResponse(err, writer)
-               return
-       }
-
-       err = handler.Handle(request)
-
-       if err != nil {
-               c.handleErrorResponse(err, writer)
-               return
-       }
-
-       writer.WriteHeader(http.StatusNoContent)
-       c.logger.Infof("[E2 Manager -> Client] #controller.handleRequest - status response: %v", http.StatusNoContent)
-}
-
-func (c *Controller) validateRequestHeader(header *http.Header) error {
-
-       if header.Get("Content-Type") != "application/json" {
-               c.logger.Errorf("#controller.validateRequestHeader - validation failure, incorrect content type")
-
-               return e2managererrors.NewHeaderValidationError()
-       }
-       return nil
-}
-
-func (c *Controller) handleErrorResponse(err error, writer http.ResponseWriter) {
-
-       var errorResponseDetails models.ErrorResponse
-       var httpError int
-
-       if err != nil {
-               switch err.(type) {
-               case *e2managererrors.RnibDbError:
-                       e2Error, _ := err.(*e2managererrors.RnibDbError)
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusInternalServerError
-               case *e2managererrors.CommandAlreadyInProgressError:
-                       e2Error, _ := err.(*e2managererrors.CommandAlreadyInProgressError)
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusMethodNotAllowed
-               case *e2managererrors.HeaderValidationError:
-                       e2Error, _ := err.(*e2managererrors.HeaderValidationError)
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusUnsupportedMediaType
-               case *e2managererrors.WrongStateError:
-                       e2Error, _ := err.(*e2managererrors.WrongStateError)
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusBadRequest
-               case *e2managererrors.RequestValidationError:
-                       e2Error, _ := err.(*e2managererrors.RequestValidationError)
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusBadRequest
-               case *e2managererrors.InvalidJsonError:
-                       e2Error, _ := err.(*e2managererrors.InvalidJsonError)
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusBadRequest
-               case *e2managererrors.RmrError:
-                       e2Error, _ := err.(*e2managererrors.RmrError)
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusInternalServerError
-               case *e2managererrors.ResourceNotFoundError:
-                       e2Error, _ := err.(*e2managererrors.ResourceNotFoundError)
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusNotFound
-
-               default:
-                       e2Error := e2managererrors.NewInternalError()
-                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
-                       httpError = http.StatusInternalServerError
-               }
-       }
-       errorResponse, _ := json.Marshal(errorResponseDetails)
-
-       c.logger.Errorf("[E2 Manager -> Client] #controller.handleErrorResponse - http status: %d, error response: %+v", httpError, errorResponseDetails)
-
-       writer.Header().Set("Content-Type", "application/json")
-       writer.WriteHeader(httpError)
-       _, err = writer.Write(errorResponse)
-
-       if err != nil {
-               c.logger.Errorf("#controller.handleErrorResponse - Cannot send response. writer:%v", writer)
-       }
-}
-
-func (c *Controller) prettifyRequest(request *http.Request) string {
-       dump, _ := httputil.DumpRequest(request, true)
-       requestPrettyPrint := strings.Replace(string(dump), "\r\n", " ", -1)
-       return strings.Replace(requestPrettyPrint, "\n", "", -1)
-}
diff --git a/E2Manager/controllers/controller_test.go b/E2Manager/controllers/controller_test.go
deleted file mode 100644 (file)
index cf5ae71..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// 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.
-//
-
-package controllers
-
-import (
-       "bytes"
-       "e2mgr/configuration"
-       "e2mgr/e2managererrors"
-       "e2mgr/e2pdus"
-       "e2mgr/logger"
-       "e2mgr/managers"
-       "e2mgr/mocks"
-       "e2mgr/models"
-       "e2mgr/providers/httpmsghandlerprovider"
-       "e2mgr/rNibWriter"
-       "e2mgr/rmrCgo"
-       "e2mgr/services"
-       "e2mgr/tests"
-       "encoding/json"
-       "fmt"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
-       "github.com/gorilla/mux"
-       "github.com/stretchr/testify/assert"
-       "github.com/stretchr/testify/mock"
-       "io"
-       "io/ioutil"
-       "net/http"
-       "net/http/httptest"
-       "strings"
-       "testing"
-)
-
-func setupControllerTest(t *testing.T) (*Controller, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock){
-       log := initLog(t)
-       config := configuration.ParseConfiguration()
-
-       rmrMessengerMock := &mocks.RmrMessengerMock{}
-       readerMock := &mocks.RnibReaderMock{}
-       readerProvider := func() reader.RNibReader {
-               return readerMock
-       }
-       writerMock := &mocks.RnibWriterMock{}
-       writerProvider := func() rNibWriter.RNibWriter {
-               return writerMock
-       }
-       rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
-
-       ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rnibDataService)
-       controller := NewController(log, getRmrService(rmrMessengerMock, log), rnibDataService, config, ranSetupManager)
-       return controller, readerMock, writerMock, rmrMessengerMock
-}
-
-func TestX2SetupInvalidBody(t *testing.T) {
-
-       controller, _, _, _ := setupControllerTest(t)
-
-       header := http.Header{}
-       header.Set("Content-Type", "application/json")
-       httpRequest, _ := http.NewRequest("POST", "http://localhost:3800/v1/nodeb/x2-setup", strings.NewReader("{}{}"))
-       httpRequest.Header = header
-
-       writer := httptest.NewRecorder()
-       controller.X2SetupHandler(writer, httpRequest)
-
-       var errorResponse = parseJsonRequest(t, writer.Body)
-
-       assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
-       assert.Equal(t, e2managererrors.NewInvalidJsonError().Code, errorResponse.Code)
-}
-
-func TestX2SetupSuccess(t *testing.T) {
-
-       controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
-
-       ranName := "test"
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ranName).Return(nb, nil)
-
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
-
-       payload := e2pdus.PackedX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
-
-       header := http.Header{}
-       header.Set("Content-Type", "application/json")
-       httpRequest := tests.GetHttpRequest()
-       httpRequest.Header = header
-
-       writer := httptest.NewRecorder()
-       controller.X2SetupHandler(writer, httpRequest)
-
-       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
-}
-
-func TestEndcSetupSuccess(t *testing.T) {
-
-       controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
-
-       ranName := "test"
-       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
-       readerMock.On("GetNodeb", ranName).Return(nb, nil)
-
-       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
-       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
-
-       payload := e2pdus.PackedEndcX2setupRequest
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
-
-       header := http.Header{}
-       header.Set("Content-Type", "application/json")
-       httpRequest := tests.GetHttpRequest()
-       httpRequest.Header = header
-
-       writer := httptest.NewRecorder()
-       controller.EndcSetupHandler(writer, httpRequest)
-
-       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
-}
-
-func TestShutdownHandlerRnibError(t *testing.T) {
-       controller, readerMock, _, _:= setupControllerTest(t)
-
-       rnibErr := &common.ResourceNotFoundError{}
-       var nbIdentityList []*entities.NbIdentity
-       readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr)
-
-       writer := httptest.NewRecorder()
-
-       controller.ShutdownHandler(writer, tests.GetHttpRequest())
-
-       var errorResponse = parseJsonRequest(t, writer.Body)
-
-       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
-       assert.Equal(t, errorResponse.Code, e2managererrors.NewRnibDbError().Code)
-}
-
-func TestHeaderValidationFailed(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
-
-       writer := httptest.NewRecorder()
-
-       header := &http.Header{}
-
-       controller.handleRequest(writer, header, httpmsghandlerprovider.ShutdownRequest, nil, true)
-
-       var errorResponse = parseJsonRequest(t, writer.Body)
-       err := e2managererrors.NewHeaderValidationError()
-
-       assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
-       assert.Equal(t, errorResponse.Code, err.Code)
-       assert.Equal(t, errorResponse.Message, err.Message)
-}
-
-func TestShutdownStatusNoContent(t *testing.T) {
-       controller, readerMock, _, _ := setupControllerTest(t)
-
-       var rnibError error
-       nbIdentityList := []*entities.NbIdentity{}
-       readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError)
-
-       writer := httptest.NewRecorder()
-       controller.ShutdownHandler(writer, tests.GetHttpRequest())
-
-       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
-}
-
-func TestHandleInternalError(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
-
-       writer := httptest.NewRecorder()
-       err := e2managererrors.NewInternalError()
-
-       controller.handleErrorResponse(err, writer)
-       var errorResponse = parseJsonRequest(t, writer.Body)
-
-       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
-       assert.Equal(t, errorResponse.Code, err.Code)
-       assert.Equal(t, errorResponse.Message, err.Message)
-}
-
-func TestHandleCommandAlreadyInProgressError(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
-       writer := httptest.NewRecorder()
-       err := e2managererrors.NewCommandAlreadyInProgressError()
-
-       controller.handleErrorResponse(err, writer)
-       var errorResponse = parseJsonRequest(t, writer.Body)
-
-       assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
-       assert.Equal(t, errorResponse.Code, err.Code)
-       assert.Equal(t, errorResponse.Message, err.Message)
-}
-
-func TestValidateHeaders(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
-
-       header := http.Header{}
-       header.Set("Content-Type", "application/json")
-       result := controller.validateRequestHeader(&header)
-
-       assert.Nil(t, result)
-}
-
-func parseJsonRequest(t *testing.T, r io.Reader) models.ErrorResponse {
-
-       var errorResponse models.ErrorResponse
-       body, err := ioutil.ReadAll(r)
-       if err != nil {
-               t.Errorf("Error cannot deserialize json request")
-       }
-       json.Unmarshal(body, &errorResponse)
-
-       return errorResponse
-}
-
-func initLog(t *testing.T) *logger.Logger {
-       log, err := logger.InitLogger(logger.InfoLevel)
-       if err != nil {
-               t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
-       }
-       return log
-}
-
-func TestX2ResetHandleSuccessfulRequestedCause(t *testing.T) {
-       controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
-
-       ranName := "test1"
-       payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
-
-       writer := httptest.NewRecorder()
-
-       var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
-       readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
-
-       data4Req := map[string]interface{}{"cause": "protocol:transfer-syntax-error"}
-       b := new(bytes.Buffer)
-       _ = json.NewEncoder(b).Encode(data4Req)
-       req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
-       req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
-
-       controller.X2ResetHandler(writer, req)
-       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
-
-}
-
-func TestX2ResetHandleSuccessfulRequestedDefault(t *testing.T) {
-       controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
-
-       ranName := "test1"
-       // o&m intervention
-       payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
-       xaction := []byte(ranName)
-       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
-
-       writer := httptest.NewRecorder()
-
-       var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
-       readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
-
-       // no body
-       b := new(bytes.Buffer)
-       req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
-       req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
-
-       controller.X2ResetHandler(writer, req)
-       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
-
-}
-
-func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
-
-       ranName := "test1"
-
-       writer := httptest.NewRecorder()
-
-       // Invalid json: attribute name without quotes (should be "cause":).
-       b := strings.NewReader("{cause:\"protocol:transfer-syntax-error\"")
-       req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
-       req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
-
-       controller.X2ResetHandler(writer, req)
-       assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
-
-}
-
-func TestHandleErrorResponse(t *testing.T) {
-       controller, _, _, _ := setupControllerTest(t)
-
-       writer := httptest.NewRecorder()
-       controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
-       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
-
-       writer = httptest.NewRecorder()
-       controller.handleErrorResponse(e2managererrors.NewCommandAlreadyInProgressError(), writer)
-       assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
-
-       writer = httptest.NewRecorder()
-       controller.handleErrorResponse(e2managererrors.NewHeaderValidationError(), writer)
-       assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
-
-       writer = httptest.NewRecorder()
-       controller.handleErrorResponse(e2managererrors.NewWrongStateError("", ""), writer)
-       assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
-
-       writer = httptest.NewRecorder()
-       controller.handleErrorResponse(e2managererrors.NewRequestValidationError(), writer)
-       assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
-
-       writer = httptest.NewRecorder()
-       controller.handleErrorResponse(e2managererrors.NewRmrError(), writer)
-       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
-
-       writer = httptest.NewRecorder()
-       controller.handleErrorResponse(e2managererrors.NewResourceNotFoundError(), writer)
-       assert.Equal(t, http.StatusNotFound, writer.Result().StatusCode)
-
-       writer = httptest.NewRecorder()
-       controller.handleErrorResponse(fmt.Errorf("ErrorError"), writer)
-       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
-}
\ No newline at end of file
index 28b713e..b1fd087 100644 (file)
 package controllers
 
 import (
+       "e2mgr/e2managererrors"
        "e2mgr/logger"
        "e2mgr/models"
-       "e2mgr/services"
-       "e2mgr/utils"
+       "e2mgr/providers/httpmsghandlerprovider"
        "encoding/json"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
-       "github.com/golang/protobuf/jsonpb"
        "github.com/gorilla/mux"
+       "io"
+       "io/ioutil"
        "net/http"
-       "time"
+       "net/http/httputil"
+       "strings"
 )
 
 const (
-       validationErrorCode       int = 402
-       notFoundErrorCode         int = 404
-       internalErrorCode         int = 501
-       validationFailedMessage       = "Validation failed"
-       notFoundErrorMessage          = "Resource not found"
-       internalErrorMessage          = "Internal Server Error. Please try again later"
+       ParamRanName = "ranName"
+       LimitRequest = 2000
 )
 
-var messageChannel chan *models.E2RequestMessage
-var errorChannel chan error
-
 type INodebController interface {
-       GetNodebIdList (writer http.ResponseWriter, request *http.Request)
-       GetNodeb(writer http.ResponseWriter, request *http.Request)
-       HandleHealthCheckRequest(writer http.ResponseWriter, request *http.Request)
+       Shutdown(writer http.ResponseWriter, r *http.Request)
+       X2Reset(writer http.ResponseWriter, r *http.Request)
+       X2Setup(writer http.ResponseWriter, r *http.Request)
+       EndcSetup(writer http.ResponseWriter, r *http.Request)
+       GetNodeb(writer http.ResponseWriter, r *http.Request)
+       GetNodebIdList(writer http.ResponseWriter, r *http.Request)
 }
 
 type NodebController struct {
-       rmrService         *services.RmrService
-       Logger             *logger.Logger
-       rnibDataService services.RNibDataService
+       logger          *logger.Logger
+       handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider
 }
 
-func NewNodebController(logger *logger.Logger, rmrService *services.RmrService, rnibDataService services.RNibDataService) *NodebController {
-       messageChannel = make(chan *models.E2RequestMessage)
-       errorChannel = make(chan error)
+func NewNodebController(logger *logger.Logger, handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider) *NodebController {
        return &NodebController{
-               rmrService:         rmrService,
-               Logger:             logger,
-               rnibDataService: rnibDataService,
+               logger:          logger,
+               handlerProvider: handlerProvider,
        }
 }
 
-func (rc NodebController) GetNodebIdList (writer http.ResponseWriter, request *http.Request) {
-       startTime := time.Now()
-       nodebIdList, rnibError := rc.rnibDataService.GetListNodebIds()
+func (c *NodebController) GetNodebIdList(writer http.ResponseWriter, r *http.Request) {
+       c.logger.Infof("[Client -> E2 Manager] #NodebController.GetNodebIdList - request: %v", c.prettifyRequest(r))
+
+       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.GetNodebIdListRequest, nil, false)
+}
+
+func (c *NodebController) GetNodeb(writer http.ResponseWriter, r *http.Request) {
+       c.logger.Infof("[Client -> E2 Manager] #NodebController.GetNodeb - request: %v", c.prettifyRequest(r))
+       vars := mux.Vars(r)
+       ranName := vars["ranName"]
+       request := models.GetNodebRequest{RanName: ranName}
+       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.GetNodebRequest, request, false)
+}
+
+func (c *NodebController) Shutdown(writer http.ResponseWriter, r *http.Request) {
+       c.logger.Infof("[Client -> E2 Manager] #NodebController.Shutdown - request: %v", c.prettifyRequest(r))
+       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ShutdownRequest, nil, false)
+}
 
-       if rnibError != nil {
-               rc.Logger.Errorf("%v", rnibError);
-               httpStatusCode, errorCode, errorMessage := rnibErrorToHttpError(rnibError)
-               handleErrorResponse(rc.Logger, httpStatusCode, errorCode, errorMessage, writer, startTime)
-               return;
+func (c *NodebController) X2Reset(writer http.ResponseWriter, r *http.Request) {
+       c.logger.Infof("[Client -> E2 Manager] #NodebController.X2Reset - request: %v", c.prettifyRequest(r))
+       request := models.ResetRequest{}
+       vars := mux.Vars(r)
+       ranName := vars[ParamRanName]
+
+       if r.ContentLength > 0 && !c.extractJsonBody(r, &request, writer) {
+               return
        }
+       request.RanName = ranName
+       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ResetRequest, request, false)
+}
+
+func (c *NodebController) X2Setup(writer http.ResponseWriter, r *http.Request) {
+       c.logger.Infof("[Client -> E2 Manager] #NodebController.X2Setup - request: %v", c.prettifyRequest(r))
 
-       pmList := utils.ConvertNodebIdListToProtoMessageList(nodebIdList)
-       result, err := utils.MarshalProtoMessageListToJsonArray(pmList)
+       request := models.SetupRequest{}
+
+       if !c.extractJsonBody(r, &request, writer) {
+               return
+       }
+
+       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.X2SetupRequest, request, true)
+}
+
+func (c *NodebController) EndcSetup(writer http.ResponseWriter, r *http.Request) {
+       c.logger.Infof("[Client -> E2 Manager] #NodebController.EndcSetup - request: %v", c.prettifyRequest(r))
+
+       request := models.SetupRequest{}
+
+       if !c.extractJsonBody(r, &request, writer) {
+               return
+       }
+
+       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.EndcSetupRequest, request, true)
+}
+
+func (c *NodebController) extractJsonBody(r *http.Request, request models.Request, writer http.ResponseWriter) bool {
+       defer r.Body.Close()
+       body, err := ioutil.ReadAll(io.LimitReader(r.Body, LimitRequest))
 
        if err != nil {
-               rc.Logger.Errorf("%v", err);
-               handleErrorResponse(rc.Logger, http.StatusInternalServerError, internalErrorCode, internalErrorMessage, writer, startTime)
-               return;
+               c.logger.Errorf("[Client -> E2 Manager] #NodebController.extractJsonBody - unable to extract json body - error: %s", err)
+               c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
+               return false
        }
 
-       writer.Header().Set("Content-Type", "application/json")
-       rc.Logger.Infof("[E2 Manager -> Client] #nodeb_controller.GetNodebIdList - response: %s", result)
-       writer.Write([]byte(result))
+       err = json.Unmarshal(body, &request)
+       if err != nil {
+               c.logger.Errorf("[Client -> E2 Manager] #NodebController.extractJsonBody - unable to extract json body - error: %s", err)
+               c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
+               return false
+       }
+
+       return true
 }
 
-func (rc NodebController) GetNodeb(writer http.ResponseWriter, request *http.Request) {
-       startTime := time.Now()
-       vars := mux.Vars(request)
-       ranName := vars["ranName"]
-       respondingNode, rnibError := rc.rnibDataService.GetNodeb(ranName)
-       if rnibError != nil {
-               rc.Logger.Errorf("%v", rnibError)
-               httpStatusCode, errorCode, errorMessage := rnibErrorToHttpError(rnibError)
-               handleErrorResponse(rc.Logger, httpStatusCode, errorCode, errorMessage, writer, startTime)
+func (c *NodebController) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest, request models.Request, validateHeader bool) {
+
+       if validateHeader {
+
+               err := c.validateRequestHeader(header)
+               if err != nil {
+                       c.handleErrorResponse(err, writer)
+                       return
+               }
+       }
+
+       handler, err := c.handlerProvider.GetHandler(requestName)
+
+       if err != nil {
+               c.handleErrorResponse(err, writer)
+               return
+       }
+
+       response, err := handler.Handle(request)
+
+       if err != nil {
+               c.handleErrorResponse(err, writer)
+               return
+       }
+
+       if response == nil {
+               writer.WriteHeader(http.StatusNoContent)
+               c.logger.Infof("[E2 Manager -> Client] #NodebController.handleRequest - status response: %v", http.StatusNoContent)
                return
        }
 
-       m := jsonpb.Marshaler{}
-       result, err := m.MarshalToString(respondingNode)
+       result, err := response.Marshal()
 
        if err != nil {
-               rc.Logger.Errorf("%v", err)
-               handleErrorResponse(rc.Logger, http.StatusInternalServerError, internalErrorCode, internalErrorMessage, writer, startTime)
+               c.handleErrorResponse(err, writer)
                return
        }
 
+       c.logger.Infof("[E2 Manager -> Client] #NodebController.handleRequest - response: %s", result)
        writer.Header().Set("Content-Type", "application/json")
-       rc.Logger.Infof("[E2 Manager -> Client] #nodeb_controller.GetNodeb - response: %s", result)
        writer.Write([]byte(result))
 }
 
-func (rc NodebController) HandleHealthCheckRequest(writer http.ResponseWriter, request *http.Request) {
-       //fmt.Println("[X-APP -> Client] #HandleHealthCheckRequest - http status: 200")
-       writer.WriteHeader(http.StatusOK)
+func (c *NodebController) validateRequestHeader(header *http.Header) error {
+
+       if header.Get("Content-Type") != "application/json" {
+               c.logger.Errorf("#NodebController.validateRequestHeader - validation failure, incorrect content type")
+
+               return e2managererrors.NewHeaderValidationError()
+       }
+       return nil
 }
 
-func handleErrorResponse(logger *logger.Logger, httpStatus int, errorCode int, errorMessage string, writer http.ResponseWriter, startTime time.Time) {
-       errorResponseDetails := models.ErrorResponse{errorCode, errorMessage}
+func (c *NodebController) handleErrorResponse(err error, writer http.ResponseWriter) {
+
+       var errorResponseDetails models.ErrorResponse
+       var httpError int
+
+       if err != nil {
+               switch err.(type) {
+               case *e2managererrors.RnibDbError:
+                       e2Error, _ := err.(*e2managererrors.RnibDbError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusInternalServerError
+               case *e2managererrors.CommandAlreadyInProgressError:
+                       e2Error, _ := err.(*e2managererrors.CommandAlreadyInProgressError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusMethodNotAllowed
+               case *e2managererrors.HeaderValidationError:
+                       e2Error, _ := err.(*e2managererrors.HeaderValidationError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusUnsupportedMediaType
+               case *e2managererrors.WrongStateError:
+                       e2Error, _ := err.(*e2managererrors.WrongStateError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusBadRequest
+               case *e2managererrors.RequestValidationError:
+                       e2Error, _ := err.(*e2managererrors.RequestValidationError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusBadRequest
+               case *e2managererrors.InvalidJsonError:
+                       e2Error, _ := err.(*e2managererrors.InvalidJsonError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusBadRequest
+               case *e2managererrors.RmrError:
+                       e2Error, _ := err.(*e2managererrors.RmrError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusInternalServerError
+               case *e2managererrors.ResourceNotFoundError:
+                       e2Error, _ := err.(*e2managererrors.ResourceNotFoundError)
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusNotFound
+
+               default:
+                       e2Error := e2managererrors.NewInternalError()
+                       errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+                       httpError = http.StatusInternalServerError
+               }
+       }
        errorResponse, _ := json.Marshal(errorResponseDetails)
-       printHandlingRequestElapsedTimeInMs(logger, startTime)
-       logger.Infof("[E2 Manager -> Client] #nodeb_controller.handleErrorResponse - http status: %d, error response: %+v", httpStatus, errorResponseDetails)
+
+       c.logger.Errorf("[E2 Manager -> Client] #NodebController.handleErrorResponse - http status: %d, error response: %+v", httpError, errorResponseDetails)
+
        writer.Header().Set("Content-Type", "application/json")
-       writer.WriteHeader(httpStatus)
-       _, err := writer.Write(errorResponse)
+       writer.WriteHeader(httpError)
+       _, err = writer.Write(errorResponse)
 
        if err != nil {
-               logger.Errorf("#nodeb_controller.handleErrorResponse - Cannot send response. writer:%v", writer)
+               c.logger.Errorf("#NodebController.handleErrorResponse - Cannot send response. writer:%v", writer)
        }
 }
 
-func printHandlingRequestElapsedTimeInMs(logger *logger.Logger, startTime time.Time) {
-       logger.Infof("Summary: #nodeb_controller.printElapsedTimeInMs - Elapsed time for handling request from client to E2 termination: %f ms",
-               float64(time.Since(startTime))/float64(time.Millisecond))
-}
-
-func rnibErrorToHttpError(rnibError error) (int, int, string) {
-       switch rnibError.(type) {
-       case *common.ResourceNotFoundError:
-               return http.StatusNotFound, notFoundErrorCode, notFoundErrorMessage
-       case *common.InternalError:
-               return http.StatusInternalServerError, internalErrorCode, internalErrorMessage
-       case *common.ValidationError:
-               return http.StatusBadRequest, validationErrorCode, validationFailedMessage
-       default:
-               return http.StatusInternalServerError, internalErrorCode, internalErrorMessage
-       }
+func (c *NodebController) prettifyRequest(request *http.Request) string {
+       dump, _ := httputil.DumpRequest(request, true)
+       requestPrettyPrint := strings.Replace(string(dump), "\r\n", " ", -1)
+       return strings.Replace(requestPrettyPrint, "\n", "", -1)
 }
index f49cd8c..f0c26e6 100644 (file)
 package controllers
 
 import (
+       "bytes"
        "e2mgr/configuration"
+       "e2mgr/e2managererrors"
+       "e2mgr/e2pdus"
        "e2mgr/logger"
+       "e2mgr/managers"
        "e2mgr/mocks"
        "e2mgr/models"
+       "e2mgr/providers/httpmsghandlerprovider"
        "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "e2mgr/tests"
+       "encoding/json"
+       "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/gorilla/mux"
        "github.com/pkg/errors"
        "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
+       "io"
        "io/ioutil"
        "net/http"
        "net/http/httptest"
+       "strings"
        "testing"
 )
 
-func setupNodebControllerTest(t *testing.T) (*logger.Logger, services.RNibDataService, *mocks.RnibReaderMock){
-       logger, err := logger.InitLogger(logger.DebugLevel)
-       if err != nil {
-               t.Errorf("#... - failed to initialize logger, error: %s", err)
-       }
-       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+type controllerGetNodebTestContext struct {
+       ranName              string
+       nodebInfo            *entities.NodebInfo
+       rnibError            error
+       expectedStatusCode   int
+       expectedJsonResponse string
+}
+
+type controllerGetNodebIdListTestContext struct {
+       nodebIdList          []*entities.NbIdentity
+       rnibError            error
+       expectedStatusCode   int
+       expectedJsonResponse string
+}
+
+func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock) {
+       log := initLog(t)
+       config := configuration.ParseConfiguration()
+
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
        readerMock := &mocks.RnibReaderMock{}
-       rnibReaderProvider := func() reader.RNibReader {
+       readerProvider := func() reader.RNibReader {
                return readerMock
        }
-       rnibWriterProvider := func() rNibWriter.RNibWriter {
-               return &mocks.RnibWriterMock{}
+       writerMock := &mocks.RnibWriterMock{}
+       writerProvider := func() rNibWriter.RNibWriter {
+               return writerMock
        }
-       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
-       return logger, rnibDataService, readerMock
+       rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
+       rmrSender := getRmrSender(rmrMessengerMock, log)
+       ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
+       handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, ranSetupManager)
+       controller := NewNodebController(log, handlerProvider)
+       return controller, readerMock, writerMock, rmrMessengerMock
 }
 
-func TestNewRequestController(t *testing.T) {
-       logger, rnibDataService, _ := setupNodebControllerTest(t)
-       assert.NotNil(t, NewNodebController(logger, &services.RmrService{}, rnibDataService))
+func TestX2SetupInvalidBody(t *testing.T) {
+
+       controller, _, _, _ := setupControllerTest(t)
+
+       header := http.Header{}
+       header.Set("Content-Type", "application/json")
+       httpRequest, _ := http.NewRequest("POST", "http://localhost:3800/v1/nodeb/x2-setup", strings.NewReader("{}{}"))
+       httpRequest.Header = header
+
+       writer := httptest.NewRecorder()
+       controller.X2Setup(writer, httpRequest)
+
+       var errorResponse = parseJsonRequest(t, writer.Body)
+
+       assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
+       assert.Equal(t, e2managererrors.NewInvalidJsonError().Code, errorResponse.Code)
 }
 
-func TestHandleHealthCheckRequest(t *testing.T) {
-       rc := NewNodebController(nil, nil, nil)
+func TestX2SetupSuccess(t *testing.T) {
+
+       controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
+
+       ranName := "test"
+       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", ranName).Return(nb, nil)
+
+       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
+       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
+
+       payload := e2pdus.PackedX2setupRequest
+       xaction := []byte(ranName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+
+       header := http.Header{}
+       header.Set("Content-Type", "application/json")
+       httpRequest := tests.GetHttpRequest()
+       httpRequest.Header = header
+
        writer := httptest.NewRecorder()
-       rc.HandleHealthCheckRequest(writer, nil)
-       assert.Equal(t, writer.Result().StatusCode, http.StatusOK)
+       controller.X2Setup(writer, httpRequest)
+
+       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
 }
 
-func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService {
-       rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       messageChannel := make(chan *models.NotificationResponse)
-       rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, messageChannel)
+func TestEndcSetupSuccess(t *testing.T) {
+
+       controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
+
+       ranName := "test"
+       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
+       readerMock.On("GetNodeb", ranName).Return(nb, nil)
+
+       var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
+       writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
+
+       payload := e2pdus.PackedEndcX2setupRequest
+       xaction := []byte(ranName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
+
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
+
+       header := http.Header{}
+       header.Set("Content-Type", "application/json")
+       httpRequest := tests.GetHttpRequest()
+       httpRequest.Header = header
+
+       writer := httptest.NewRecorder()
+       controller.EndcSetup(writer, httpRequest)
+
+       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
 }
 
-func executeGetNodeb(logger *logger.Logger, writer *httptest.ResponseRecorder, rnibDataService services.RNibDataService) {
-       req, _ := http.NewRequest("GET", "/nodeb", nil)
-       req = mux.SetURLVars(req, map[string]string{"ranName": "testNode"})
+func TestShutdownHandlerRnibError(t *testing.T) {
+       controller, readerMock, _, _ := setupControllerTest(t)
 
-       NewNodebController(logger, nil, rnibDataService).GetNodeb(writer, req)
+       rnibErr := &common.ResourceNotFoundError{}
+       var nbIdentityList []*entities.NbIdentity
+       readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr)
+
+       writer := httptest.NewRecorder()
+
+       controller.Shutdown(writer, tests.GetHttpRequest())
+
+       var errorResponse = parseJsonRequest(t, writer.Body)
+
+       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+       assert.Equal(t, errorResponse.Code, e2managererrors.NewRnibDbError().Code)
 }
 
-func TestNodebController_GetNodeb_Success(t *testing.T) {
-       logger, rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+func controllerGetNodebTestExecuter(t *testing.T, context *controllerGetNodebTestContext) {
+       controller, readerMock, _, _ := setupControllerTest(t)
+       writer := httptest.NewRecorder()
+       readerMock.On("GetNodeb", context.ranName).Return(context.nodebInfo, context.rnibError)
+       req, _ := http.NewRequest("GET", "/nodeb", nil)
+       req = mux.SetURLVars(req, map[string]string{"ranName": context.ranName})
+       controller.GetNodeb(writer, req)
+       assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode)
+       bodyBytes, _ := ioutil.ReadAll(writer.Body)
+       assert.Equal(t, context.expectedJsonResponse, string(bodyBytes))
+}
 
+func controllerGetNodebIdListTestExecuter(t *testing.T, context *controllerGetNodebIdListTestContext) {
+       controller, readerMock, _, _ := setupControllerTest(t)
        writer := httptest.NewRecorder()
+       readerMock.On("GetListNodebIds").Return(context.nodebIdList, context.rnibError)
+       req, _ := http.NewRequest("GET", "/nodeb/ids", nil)
+       controller.GetNodebIdList(writer, req)
+       assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode)
+       bodyBytes, _ := ioutil.ReadAll(writer.Body)
+       assert.Equal(t, context.expectedJsonResponse, string(bodyBytes))
+}
+
+func TestControllerGetNodebSuccess(t *testing.T) {
+       ranName := "test"
+       var rnibError error
+       context := controllerGetNodebTestContext{
+               ranName:              ranName,
+               nodebInfo:            &entities.NodebInfo{RanName: ranName, Ip: "10.0.2.15", Port: 1234},
+               rnibError:            rnibError,
+               expectedStatusCode:   http.StatusOK,
+               expectedJsonResponse: fmt.Sprintf("{\"ranName\":\"%s\",\"ip\":\"10.0.2.15\",\"port\":1234}", ranName),
+       }
+
+       controllerGetNodebTestExecuter(t, &context)
+}
 
+func TestControllerGetNodebNotFound(t *testing.T) {
 
+       ranName := "test"
+       var nodebInfo *entities.NodebInfo
+       context := controllerGetNodebTestContext{
+               ranName:              ranName,
+               nodebInfo:            nodebInfo,
+               rnibError:            common.NewResourceNotFoundError("#reader.GetNodeb - Not found Error"),
+               expectedStatusCode:   http.StatusNotFound,
+               expectedJsonResponse: "{\"errorCode\":404,\"errorMessage\":\"Resource not found\"}",
+       }
+
+       controllerGetNodebTestExecuter(t, &context)
+}
+
+func TestControllerGetNodebInternal(t *testing.T) {
+       ranName := "test"
+       var nodebInfo *entities.NodebInfo
+       context := controllerGetNodebTestContext{
+               ranName:              ranName,
+               nodebInfo:            nodebInfo,
+               rnibError:            common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")),
+               expectedStatusCode:   http.StatusInternalServerError,
+               expectedJsonResponse: "{\"errorCode\":500,\"errorMessage\":\"RNIB error\"}",
+       }
+
+       controllerGetNodebTestExecuter(t, &context)
+}
+
+func TestControllerGetNodebIdListSuccess(t *testing.T) {
        var rnibError error
-       rnibReaderMock.On("GetNodeb", "testNode").Return(&entities.NodebInfo{}, rnibError)
+       nodebIdList := []*entities.NbIdentity{
+               {InventoryName: "test1", GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId1", NbId: "nbId1"}},
+               {InventoryName: "test2", GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId2", NbId: "nbId2"}},
+       }
 
-       executeGetNodeb(logger, writer, rnibDataService)
+       context := controllerGetNodebIdListTestContext{
+               nodebIdList:          nodebIdList,
+               rnibError:            rnibError,
+               expectedStatusCode:   http.StatusOK,
+               expectedJsonResponse: "[{\"inventoryName\":\"test1\",\"globalNbId\":{\"plmnId\":\"plmnId1\",\"nbId\":\"nbId1\"}},{\"inventoryName\":\"test2\",\"globalNbId\":{\"plmnId\":\"plmnId2\",\"nbId\":\"nbId2\"}}]",
+       }
 
-       assert.Equal(t, writer.Result().StatusCode, http.StatusOK)
+       controllerGetNodebIdListTestExecuter(t, &context)
 }
 
-func TestNodebController_GetNodeb_NotFound(t *testing.T) {
-       logger, rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+func TestControllerGetNodebIdListEmptySuccess(t *testing.T) {
+       var rnibError error
+       nodebIdList := []*entities.NbIdentity{}
 
-       writer := httptest.NewRecorder()
+       context := controllerGetNodebIdListTestContext{
+               nodebIdList:          nodebIdList,
+               rnibError:            rnibError,
+               expectedStatusCode:   http.StatusOK,
+               expectedJsonResponse: "[]",
+       }
 
-       rnibError := common.NewResourceNotFoundErrorf("#reader.GetNodeb - responding node %s not found", "testNode")
-       var nodebInfo *entities.NodebInfo
-       rnibReaderMock.On("GetNodeb", "testNode").Return(nodebInfo, rnibError)
+       controllerGetNodebIdListTestExecuter(t, &context)
+}
+
+func TestControllerGetNodebIdListInternal(t *testing.T) {
+       var nodebIdList []*entities.NbIdentity
+       context := controllerGetNodebIdListTestContext{
+               nodebIdList:          nodebIdList,
+               rnibError:            common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")),
+               expectedStatusCode:   http.StatusInternalServerError,
+               expectedJsonResponse: "{\"errorCode\":500,\"errorMessage\":\"RNIB error\"}",
+       }
 
-       executeGetNodeb(logger, writer, rnibDataService)
-       assert.Equal(t, writer.Result().StatusCode, http.StatusNotFound)
+       controllerGetNodebIdListTestExecuter(t, &context)
 }
 
-func TestNodebController_GetNodeb_InternalError(t *testing.T) {
-       logger, rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+func TestHeaderValidationFailed(t *testing.T) {
+       controller, _, _, _ := setupControllerTest(t)
 
        writer := httptest.NewRecorder()
 
-       rnibError := common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error"))
-       var nodebInfo *entities.NodebInfo
-       rnibReaderMock.On("GetNodeb", "testNode").Return(nodebInfo, rnibError)
+       header := &http.Header{}
+
+       controller.handleRequest(writer, header, httpmsghandlerprovider.ShutdownRequest, nil, true)
+
+       var errorResponse = parseJsonRequest(t, writer.Body)
+       err := e2managererrors.NewHeaderValidationError()
 
-       executeGetNodeb(logger, writer, rnibDataService)
-       assert.Equal(t, writer.Result().StatusCode, http.StatusInternalServerError)
+       assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
+       assert.Equal(t, errorResponse.Code, err.Code)
+       assert.Equal(t, errorResponse.Message, err.Message)
 }
 
-func executeGetNodebIdList(logger *logger.Logger, writer *httptest.ResponseRecorder, rnibDataService services.RNibDataService) {
-       req, _ := http.NewRequest("GET", "/nodeb-ids", nil)
-       NewNodebController(logger, nil, rnibDataService).GetNodebIdList(writer,req)
+func TestShutdownStatusNoContent(t *testing.T) {
+       controller, readerMock, _, _ := setupControllerTest(t)
+
+       var rnibError error
+       nbIdentityList := []*entities.NbIdentity{}
+       readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError)
+
+       writer := httptest.NewRecorder()
+       controller.Shutdown(writer, tests.GetHttpRequest())
+
+       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
 }
 
-func TestNodebController_GetNodebIdList_Success(t *testing.T) {
-       logger, rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+func TestHandleInternalError(t *testing.T) {
+       controller, _, _, _ := setupControllerTest(t)
+
        writer := httptest.NewRecorder()
+       err := e2managererrors.NewInternalError()
 
-       var rnibError error
+       controller.handleErrorResponse(err, writer)
+       var errorResponse = parseJsonRequest(t, writer.Body)
 
-       nbList := []*entities.NbIdentity{
-               {InventoryName: "test1", GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId1", NbId: "nbId1"}},
-               {InventoryName: "test2", GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId2", NbId: "nbId2"}},
-               {InventoryName: "test3", GlobalNbId: &entities.GlobalNbId{PlmnId: "", NbId: ""}},
+       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+       assert.Equal(t, errorResponse.Code, err.Code)
+       assert.Equal(t, errorResponse.Message, err.Message)
+}
+
+func TestHandleCommandAlreadyInProgressError(t *testing.T) {
+       controller, _, _, _ := setupControllerTest(t)
+       writer := httptest.NewRecorder()
+       err := e2managererrors.NewCommandAlreadyInProgressError()
+
+       controller.handleErrorResponse(err, writer)
+       var errorResponse = parseJsonRequest(t, writer.Body)
+
+       assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
+       assert.Equal(t, errorResponse.Code, err.Code)
+       assert.Equal(t, errorResponse.Message, err.Message)
+}
+
+func TestValidateHeaders(t *testing.T) {
+       controller, _, _, _ := setupControllerTest(t)
+
+       header := http.Header{}
+       header.Set("Content-Type", "application/json")
+       result := controller.validateRequestHeader(&header)
+
+       assert.Nil(t, result)
+}
+
+func parseJsonRequest(t *testing.T, r io.Reader) models.ErrorResponse {
+
+       var errorResponse models.ErrorResponse
+       body, err := ioutil.ReadAll(r)
+       if err != nil {
+               t.Errorf("Error cannot deserialize json request")
        }
-       rnibReaderMock.On("GetListNodebIds").Return(nbList, rnibError)
+       json.Unmarshal(body, &errorResponse)
 
-       executeGetNodebIdList(logger, writer, rnibDataService)
-       assert.Equal(t, writer.Result().StatusCode, http.StatusOK)
-       bodyBytes, _ := ioutil.ReadAll(writer.Body)
-       assert.Equal(t, "[{\"inventoryName\":\"test1\",\"globalNbId\":{\"plmnId\":\"plmnId1\",\"nbId\":\"nbId1\"}},{\"inventoryName\":\"test2\",\"globalNbId\":{\"plmnId\":\"plmnId2\",\"nbId\":\"nbId2\"}},{\"inventoryName\":\"test3\",\"globalNbId\":{}}]", string(bodyBytes))
+       return errorResponse
+}
+
+func initLog(t *testing.T) *logger.Logger {
+       log, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
+       }
+       return log
 }
 
-func TestNodebController_GetNodebIdList_EmptyList(t *testing.T) {
-       logger, rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+func TestX2ResetHandleSuccessfulRequestedCause(t *testing.T) {
+       controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
+
+       ranName := "test1"
+       payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
+       xaction := []byte(ranName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
+       rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
 
        writer := httptest.NewRecorder()
 
-       var rnibError error
-       nbList := []*entities.NbIdentity{}
-       rnibReaderMock.On("GetListNodebIds").Return(nbList, rnibError)
+       var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+       readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
 
+       data4Req := map[string]interface{}{"cause": "protocol:transfer-syntax-error"}
+       b := new(bytes.Buffer)
+       _ = json.NewEncoder(b).Encode(data4Req)
+       req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
+       req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
 
-       executeGetNodebIdList(logger, writer, rnibDataService)
+       controller.X2Reset(writer, req)
+       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
+
+}
+
+func TestX2ResetHandleSuccessfulRequestedDefault(t *testing.T) {
+       controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
+
+       ranName := "test1"
+       // o&m intervention
+       payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
+       xaction := []byte(ranName)
+       msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
+       rmrMessengerMock.On("SendMsg", msg).Return(msg, nil)
+
+       writer := httptest.NewRecorder()
+
+       var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+       readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
+
+       // no body
+       b := new(bytes.Buffer)
+       req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
+       req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
+
+       controller.X2Reset(writer, req)
+       assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
+
+}
+
+func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
+       controller, _, _, _ := setupControllerTest(t)
+
+       ranName := "test1"
+
+       writer := httptest.NewRecorder()
+
+       // Invalid json: attribute name without quotes (should be "cause":).
+       b := strings.NewReader("{cause:\"protocol:transfer-syntax-error\"")
+       req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
+       req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
+
+       controller.X2Reset(writer, req)
+       assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
 
-       assert.Equal(t, writer.Result().StatusCode, http.StatusOK)
-       bodyBytes, _ := ioutil.ReadAll(writer.Body)
-       assert.Equal(t, "[]", string(bodyBytes))
 }
 
-func TestNodebController_GetNodebIdList_InternalError(t *testing.T) {
-       logger, rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+func TestHandleErrorResponse(t *testing.T) {
+       controller, _, _, _ := setupControllerTest(t)
 
        writer := httptest.NewRecorder()
+       controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
+       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+
+       writer = httptest.NewRecorder()
+       controller.handleErrorResponse(e2managererrors.NewCommandAlreadyInProgressError(), writer)
+       assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
 
-       rnibError := common.NewInternalError(errors.New("#reader.GetEnbIdList - Internal Error"))
-       var nbList []*entities.NbIdentity
-       rnibReaderMock.On("GetListNodebIds").Return(nbList, rnibError)
+       writer = httptest.NewRecorder()
+       controller.handleErrorResponse(e2managererrors.NewHeaderValidationError(), writer)
+       assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
 
-       executeGetNodebIdList(logger, writer, rnibDataService)
-       assert.Equal(t, writer.Result().StatusCode, http.StatusInternalServerError)
+       writer = httptest.NewRecorder()
+       controller.handleErrorResponse(e2managererrors.NewWrongStateError("", ""), writer)
+       assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
+
+       writer = httptest.NewRecorder()
+       controller.handleErrorResponse(e2managererrors.NewRequestValidationError(), writer)
+       assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
+
+       writer = httptest.NewRecorder()
+       controller.handleErrorResponse(e2managererrors.NewRmrError(), writer)
+       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+
+       writer = httptest.NewRecorder()
+       controller.handleErrorResponse(e2managererrors.NewResourceNotFoundError(), writer)
+       assert.Equal(t, http.StatusNotFound, writer.Result().StatusCode)
+
+       writer = httptest.NewRecorder()
+       controller.handleErrorResponse(fmt.Errorf("ErrorError"), writer)
+       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+}
+
+func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
+       rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
+       rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
+       return rmrsender.NewRmrSender(log, &rmrMessenger)
 }
diff --git a/E2Manager/controllers/root_controller.go b/E2Manager/controllers/root_controller.go
new file mode 100644 (file)
index 0000000..605a9c2
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package controllers
+
+import (
+       "e2mgr/services"
+       "net/http"
+)
+
+type IRootController interface {
+       HandleHealthCheckRequest(writer http.ResponseWriter, request *http.Request)
+}
+
+type RootController struct {
+       rnibDataService services.RNibDataService
+}
+
+func NewRootController(rnibDataService services.RNibDataService) *RootController {
+       return &RootController{
+               rnibDataService: rnibDataService,
+       }
+}
+
+func (rc *RootController) HandleHealthCheckRequest(writer http.ResponseWriter, request *http.Request) {
+       httpStatus := http.StatusOK
+       isOn := rc.rnibDataService.PingRnib()
+       if !isOn {
+               httpStatus = http.StatusInternalServerError
+       }
+
+       writer.WriteHeader(httpStatus)
+}
diff --git a/E2Manager/controllers/root_controller_test.go b/E2Manager/controllers/root_controller_test.go
new file mode 100644 (file)
index 0000000..7001eef
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package controllers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "e2mgr/rNibWriter"
+       "e2mgr/services"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
+       "github.com/stretchr/testify/assert"
+       "net"
+       "net/http"
+       "net/http/httptest"
+       "testing"
+)
+
+func setupNodebControllerTest(t *testing.T) (services.RNibDataService, *mocks.RnibReaderMock){
+       logger, err := logger.InitLogger(logger.DebugLevel)
+       if err != nil {
+               t.Errorf("#... - failed to initialize logger, error: %s", err)
+       }
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+       readerMock := &mocks.RnibReaderMock{}
+       rnibReaderProvider := func() reader.RNibReader {
+               return readerMock
+       }
+       rnibWriterProvider := func() rNibWriter.RNibWriter {
+               return &mocks.RnibWriterMock{}
+       }
+       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+       return rnibDataService, readerMock
+}
+
+func TestNewRequestController(t *testing.T) {
+       rnibDataService, _ := setupNodebControllerTest(t)
+       assert.NotNil(t, NewRootController(rnibDataService))
+}
+
+func TestHandleHealthCheckRequestGood(t *testing.T) {
+       rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+
+       var nbList []*entities.NbIdentity
+       rnibReaderMock.On("GetListNodebIds").Return(nbList, nil)
+
+       rc := NewRootController(rnibDataService)
+       writer := httptest.NewRecorder()
+       rc.HandleHealthCheckRequest(writer, nil)
+       assert.Equal(t, http.StatusOK, writer.Result().StatusCode)
+}
+
+func TestHandleHealthCheckRequestOtherError(t *testing.T) {
+       rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+
+       mockOtherErr := &common.InternalError{Err: fmt.Errorf("non connection error")}
+       var nbList []*entities.NbIdentity
+       rnibReaderMock.On("GetListNodebIds").Return(nbList, mockOtherErr)
+
+       rc := NewRootController(rnibDataService)
+       writer := httptest.NewRecorder()
+       rc.HandleHealthCheckRequest(writer, nil)
+       assert.Equal(t, http.StatusOK, writer.Result().StatusCode)
+}
+
+func TestHandleHealthCheckRequestConnError(t *testing.T) {
+       rnibDataService, rnibReaderMock := setupNodebControllerTest(t)
+
+       mockConnErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       var nbList []*entities.NbIdentity
+       rnibReaderMock.On("GetListNodebIds").Return(nbList, mockConnErr)
+
+
+       rc := NewRootController(rnibDataService)
+       writer := httptest.NewRecorder()
+       rc.HandleHealthCheckRequest(writer, nil)
+       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+}
\ No newline at end of file
@@ -23,6 +23,7 @@ package converters
 // #include <load_information_wrapper.h>
 import "C"
 import (
+       "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "unsafe"
@@ -36,6 +37,20 @@ const (
        MaxNoOfPa                = 3
 )
 
+type EnbLoadInformationExtractor struct {
+       logger *logger.Logger
+}
+
+type IEnbLoadInformationExtractor interface {
+       ExtractAndBuildRanLoadInformation(pdu *C.E2AP_PDU_t, ranLoadInformation *entities.RanLoadInformation) error
+}
+
+func NewEnbLoadInformationExtractor(logger *logger.Logger) *EnbLoadInformationExtractor {
+       return &EnbLoadInformationExtractor{
+               logger: logger,
+       }
+}
+
 var populators = map[C.CellInformation_Item_ExtIEs__extensionValue_PR]func(string, *entities.CellLoadInformation, *C.CellInformation_Item_ExtIEs_t) error{
        C.CellInformation_Item_ExtIEs__extensionValue_PR_ABSInformation:                     populateAbsInformation,
        C.CellInformation_Item_ExtIEs__extensionValue_PR_InvokeIndication:                   populateInvokeIndication,
@@ -649,7 +664,7 @@ func populateCellLoadInformationExtensionIEs(cellId string, cellLoadInformation
        return nil
 }
 
-func ExtractAndBuildRanLoadInformation(pdu *C.E2AP_PDU_t, ranLoadInformation *entities.RanLoadInformation) error {
+func (*EnbLoadInformationExtractor) ExtractAndBuildRanLoadInformation(pdu *C.E2AP_PDU_t, ranLoadInformation *entities.RanLoadInformation) error {
 
        defer C.delete_pdu(pdu)
 
diff --git a/E2Manager/converters/x2_reset_response_extractor.go b/E2Manager/converters/x2_reset_response_extractor.go
new file mode 100644 (file)
index 0000000..32752d2
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package converters
+
+// #cgo CFLAGS: -I../asn1codec/inc/ -I../asn1codec/e2ap_engine/
+// #cgo LDFLAGS: -L ../asn1codec/lib/ -L../asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
+// #include <asn1codec_utils.h>
+// #include <SuccessfulOutcome.h>
+import "C"
+import (
+       "e2mgr/e2pdus"
+       "e2mgr/logger"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "unsafe"
+)
+
+type X2ResetResponseExtractor struct {
+       logger *logger.Logger
+}
+
+func NewX2ResetResponseExtractor(logger *logger.Logger) *X2ResetResponseExtractor {
+       return &X2ResetResponseExtractor{
+               logger: logger,
+       }
+}
+
+type IX2ResetResponseExtractor interface {
+       ExtractCriticalityDiagnosticsFromPdu(packedBuffer []byte) (*entities.CriticalityDiagnostics, error)
+}
+
+func (e *X2ResetResponseExtractor) ExtractCriticalityDiagnosticsFromPdu(packedBuffer []byte) (*entities.CriticalityDiagnostics, error) {
+       pdu, err := UnpackX2apPdu(e.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuffer), packedBuffer, e2pdus.MaxAsn1CodecMessageBufferSize)
+
+       if err != nil {
+               return nil, err
+       }
+
+       if pdu.present != C.E2AP_PDU_PR_successfulOutcome {
+               return nil, fmt.Errorf("Invalid E2AP_PDU value")
+       }
+
+       successfulOutcome := *(**C.SuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
+
+       if successfulOutcome == nil || successfulOutcome.value.present != C.SuccessfulOutcome__value_PR_ResetResponse {
+               return nil, fmt.Errorf("Unexpected SuccessfulOutcome value")
+       }
+
+       resetResponse := (*C.ResetResponse_t)(unsafe.Pointer(&successfulOutcome.value.choice[0]))
+
+       protocolIEsListCount := resetResponse.protocolIEs.list.count
+
+       if protocolIEsListCount == 0 {
+               return nil, nil
+       }
+
+       if protocolIEsListCount != 1 {
+               return nil, fmt.Errorf("Invalid protocolIEs list count")
+       }
+
+       resetResponseIEs := (*[1 << 30]*C.ResetResponse_IEs_t)(unsafe.Pointer(resetResponse.protocolIEs.list.array))[:int(protocolIEsListCount):int(protocolIEsListCount)]
+
+       resetResponseIE := resetResponseIEs[0]
+
+       if resetResponseIE.value.present != C.ResetResponse_IEs__value_PR_CriticalityDiagnostics {
+               return nil, fmt.Errorf("Invalid protocolIEs value")
+       }
+
+       cd := (*C.CriticalityDiagnostics_t)(unsafe.Pointer(&resetResponseIE.value.choice[0]))
+
+       return getCriticalityDiagnostics(cd)
+}
@@ -23,6 +23,7 @@ package converters
 // #include <x2setup_response_wrapper.h>
 import "C"
 import (
+       "e2mgr/e2pdus"
        "e2mgr/logger"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "unsafe"
@@ -32,6 +33,20 @@ const (
        maxNrOfErrors = 256
 )
 
+type X2SetupFailureResponseConverter struct {
+       logger *logger.Logger
+}
+
+type IX2SetupFailureResponseConverter interface {
+       UnpackX2SetupFailureResponseAndExtract(packedBuf []byte) (*entities.SetupFailure, error)
+}
+
+func NewX2SetupFailureResponseConverter(logger *logger.Logger) *X2SetupFailureResponseConverter {
+       return &X2SetupFailureResponseConverter{
+               logger: logger,
+       }
+}
+
 // The following are possible values of a choice field, find which the pdu contains.
 func getCause(causeIE *C.Cause_t, setupFailure *entities.SetupFailure) error {
        switch causeIE.present {
@@ -138,8 +153,8 @@ func x2SetupFailureResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.SetupFailure
        return &setupFailure, nil
 }
 
-func UnpackX2SetupFailureResponseAndExtract(logger *logger.Logger, allocationBufferSize int, packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (*entities.SetupFailure, error) {
-       pdu, err := UnpackX2apPdu(logger, allocationBufferSize, packedBufferSize, packedBuf, maxMessageBufferSize)
+func (c *X2SetupFailureResponseConverter) UnpackX2SetupFailureResponseAndExtract(packedBuf []byte) (*entities.SetupFailure, error) {
+       pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
        if err != nil {
                return nil, err
        }
@@ -147,4 +162,4 @@ func UnpackX2SetupFailureResponseAndExtract(logger *logger.Logger, allocationBuf
        defer C.delete_pdu(pdu)
 
        return x2SetupFailureResponseToProtobuf(pdu)
-}
+}
\ No newline at end of file
@@ -18,7 +18,6 @@
 package converters
 
 import (
-       "e2mgr/e2pdus"
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -28,7 +27,7 @@ import (
 
 /*
 Test permutations of x2 setup response to protobuf enb
- */
+*/
 
 func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
        logger, _ := logger.InitLogger(logger.InfoLevel)
@@ -41,145 +40,145 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                {
                        response: "CONNECTED_SETUP_FAILED network_layer_cause:HANDOVER_DESIRABLE_FOR_RADIO_REASONS time_to_wait:V1S criticality_diagnostics:<procedure_code:33 triggering_message:UNSUCCESSFUL_OUTCOME procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
                        /*
-                       E2AP-PDU:
-                        unsuccessfulOutcome_t
-                         procedureCode_t = 0x6
-                         criticality_t = 0
-                         X2SetupFailure
-                          protocolIEs_t:
-                           ProtocolIE_Container_elm
-                            id_t = 0x5
-                            criticality_t = 0x1
-                            Cause:
-                             radioNetwork_t = 0
-                           ProtocolIE_Container_elm
-                            id_t = 0x16
-                            criticality_t = 0x1
-                            TimeToWait = 0
-                           ProtocolIE_Container_elm
-                            id_t = 0x11
-                            criticality_t = 0x1
-                            CriticalityDiagnostics
-                             procedureCode_t = 0x21
-                             triggeringMessage_t = 0x2
-                             procedureCriticality_t = 0x2
-                             iEsCriticalityDiagnostics_t:
-                              CriticalityDiagnostics_IE_List_elm
-                               iECriticality_t = 0
-                               iE_ID_t = 0x80
-                               typeOfError_t = 0x1
+                               E2AP-PDU:
+                                unsuccessfulOutcome_t
+                                 procedureCode_t = 0x6
+                                 criticality_t = 0
+                                 X2SetupFailure
+                                  protocolIEs_t:
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x5
+                                    criticality_t = 0x1
+                                    Cause:
+                                     radioNetwork_t = 0
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x16
+                                    criticality_t = 0x1
+                                    TimeToWait = 0
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x11
+                                    criticality_t = 0x1
+                                    CriticalityDiagnostics
+                                     procedureCode_t = 0x21
+                                     triggeringMessage_t = 0x2
+                                     procedureCriticality_t = 0x2
+                                     iEsCriticalityDiagnostics_t:
+                                      CriticalityDiagnostics_IE_List_elm
+                                       iECriticality_t = 0
+                                       iE_ID_t = 0x80
+                                       typeOfError_t = 0x1
                        */
                        packedPdu: "4006001a0000030005400200000016400100001140087821a00000008040"},
                {
                        response: "CONNECTED_SETUP_FAILED transport_layer_cause:TRANSPORT_RESOURCE_UNAVAILABLE criticality_diagnostics:<procedure_code:33 triggering_message:UNSUCCESSFUL_OUTCOME procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
                        /*
-                       E2AP-PDU:
-                        unsuccessfulOutcome_t
-                         procedureCode_t = 0x6
-                         criticality_t = 0
-                         X2SetupFailure
-                          protocolIEs_t:
-                           ProtocolIE_Container_elm
-                            id_t = 0x5
-                            criticality_t = 0x1
-                            Cause:
-                             transport_t = 0
-                           ProtocolIE_Container_elm
-                            id_t = 0x11
-                            criticality_t = 0x1
-                            CriticalityDiagnostics
-                             procedureCode_t = 0x21
-                             triggeringMessage_t = 0x2
-                             procedureCriticality_t = 0x2
-                             iEsCriticalityDiagnostics_t:
-                              CriticalityDiagnostics_IE_List_elm
-                               iECriticality_t = 0
-                               iE_ID_t = 0x80
-                               typeOfError_t = 0x1
+                               E2AP-PDU:
+                                unsuccessfulOutcome_t
+                                 procedureCode_t = 0x6
+                                 criticality_t = 0
+                                 X2SetupFailure
+                                  protocolIEs_t:
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x5
+                                    criticality_t = 0x1
+                                    Cause:
+                                     transport_t = 0
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x11
+                                    criticality_t = 0x1
+                                    CriticalityDiagnostics
+                                     procedureCode_t = 0x21
+                                     triggeringMessage_t = 0x2
+                                     procedureCriticality_t = 0x2
+                                     iEsCriticalityDiagnostics_t:
+                                      CriticalityDiagnostics_IE_List_elm
+                                       iECriticality_t = 0
+                                       iE_ID_t = 0x80
+                                       typeOfError_t = 0x1
                        */
                        packedPdu: "400600140000020005400120001140087821a00000008040"},
                {
                        response: "CONNECTED_SETUP_FAILED protocol_cause:ABSTRACT_SYNTAX_ERROR_IGNORE_AND_NOTIFY criticality_diagnostics:<triggering_message:UNSUCCESSFUL_OUTCOME procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
                        /*
-                       E2AP-PDU:
-                        unsuccessfulOutcome_t
-                         procedureCode_t = 0x6
-                         criticality_t = 0
-                         X2SetupFailure
-                          protocolIEs_t:
-                           ProtocolIE_Container_elm
-                            id_t = 0x5
-                            criticality_t = 0x1
-                            Cause:
-                             protocol_t = 0x2
-                           ProtocolIE_Container_elm
-                            id_t = 0x11
-                            criticality_t = 0x1
-                            CriticalityDiagnostics
-                             triggeringMessage_t = 0x2
-                             procedureCriticality_t = 0x2
-                             iEsCriticalityDiagnostics_t:
-                              CriticalityDiagnostics_IE_List_elm
-                               iECriticality_t = 0
-                               iE_ID_t = 0x80
-                               typeOfError_t = 0x1
+                               E2AP-PDU:
+                                unsuccessfulOutcome_t
+                                 procedureCode_t = 0x6
+                                 criticality_t = 0
+                                 X2SetupFailure
+                                  protocolIEs_t:
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x5
+                                    criticality_t = 0x1
+                                    Cause:
+                                     protocol_t = 0x2
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x11
+                                    criticality_t = 0x1
+                                    CriticalityDiagnostics
+                                     triggeringMessage_t = 0x2
+                                     procedureCriticality_t = 0x2
+                                     iEsCriticalityDiagnostics_t:
+                                      CriticalityDiagnostics_IE_List_elm
+                                       iECriticality_t = 0
+                                       iE_ID_t = 0x80
+                                       typeOfError_t = 0x1
                        */
                        packedPdu: "400600130000020005400144001140073a800000008040"},
 
                {
                        response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED criticality_diagnostics:<procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
                        /*
-                       E2AP-PDU:
-                        unsuccessfulOutcome_t
-                         procedureCode_t = 0x6
-                         criticality_t = 0
-                         X2SetupFailure
-                          protocolIEs_t:
-                           ProtocolIE_Container_elm
-                            id_t = 0x5
-                            criticality_t = 0x1
-                            Cause:
-                             misc_t = 0x4
-                           ProtocolIE_Container_elm
-                            id_t = 0x11
-                            criticality_t = 0x1
-                            CriticalityDiagnostics
-                             procedureCriticality_t = 0x2
-                             iEsCriticalityDiagnostics_t:
-                              CriticalityDiagnostics_IE_List_elm
-                               iECriticality_t = 0
-                               iE_ID_t = 0x80
-                               typeOfError_t = 0x1
+                               E2AP-PDU:
+                                unsuccessfulOutcome_t
+                                 procedureCode_t = 0x6
+                                 criticality_t = 0
+                                 X2SetupFailure
+                                  protocolIEs_t:
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x5
+                                    criticality_t = 0x1
+                                    Cause:
+                                     misc_t = 0x4
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x11
+                                    criticality_t = 0x1
+                                    CriticalityDiagnostics
+                                     procedureCriticality_t = 0x2
+                                     iEsCriticalityDiagnostics_t:
+                                      CriticalityDiagnostics_IE_List_elm
+                                       iECriticality_t = 0
+                                       iE_ID_t = 0x80
+                                       typeOfError_t = 0x1
                        */
                        packedPdu: "400600120000020005400168001140061a0000008040"},
 
                {
                        response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED criticality_diagnostics:<information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > information_element_criticality_diagnostics:<ie_criticality:NOTIFY ie_id:255 type_of_error:NOT_UNDERSTOOD > > ",
                        /*
-                       E2AP-PDU:
-                        unsuccessfulOutcome_t
-                         procedureCode_t = 0x6
-                         criticality_t = 0
-                         X2SetupFailure
-                          protocolIEs_t:
-                           ProtocolIE_Container_elm
-                            id_t = 0x5
-                            criticality_t = 0x1
-                            Cause:
-                             misc_t = 0x4
-                           ProtocolIE_Container_elm
-                            id_t = 0x11
-                            criticality_t = 0x1
-                            CriticalityDiagnostics
-                             iEsCriticalityDiagnostics_t:
-                              CriticalityDiagnostics_IE_List_elm
-                               iECriticality_t = 0
-                               iE_ID_t = 0x80
-                               typeOfError_t = 0x1
-                              CriticalityDiagnostics_IE_List_elm
-                               iECriticality_t = 0x2
-                               iE_ID_t = 0xff
-                               typeOfError_t = 0
+                               E2AP-PDU:
+                                unsuccessfulOutcome_t
+                                 procedureCode_t = 0x6
+                                 criticality_t = 0
+                                 X2SetupFailure
+                                  protocolIEs_t:
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x5
+                                    criticality_t = 0x1
+                                    Cause:
+                                     misc_t = 0x4
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x11
+                                    criticality_t = 0x1
+                                    CriticalityDiagnostics
+                                     iEsCriticalityDiagnostics_t:
+                                      CriticalityDiagnostics_IE_List_elm
+                                       iECriticality_t = 0
+                                       iE_ID_t = 0x80
+                                       typeOfError_t = 0x1
+                                      CriticalityDiagnostics_IE_List_elm
+                                       iECriticality_t = 0x2
+                                       iE_ID_t = 0xff
+                                       typeOfError_t = 0
                        */
                        packedPdu: "4006001500000200054001680011400908010000804800ff00"},
 
@@ -187,39 +186,39 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                {
                        response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED criticality_diagnostics:<procedure_code:33 > ",
                        /*
-                       E2AP-PDU:
-                        unsuccessfulOutcome_t
-                         procedureCode_t = 0x6
-                         criticality_t = 0
-                         X2SetupFailure
-                          protocolIEs_t:
-                           ProtocolIE_Container_elm
-                            id_t = 0x5
-                            criticality_t = 0x1
-                            Cause:
-                             misc_t = 0x4
-                           ProtocolIE_Container_elm
-                            id_t = 0x11
-                            criticality_t = 0x1
-                            CriticalityDiagnostics
-                             procedureCode_t = 0x21
+                               E2AP-PDU:
+                                unsuccessfulOutcome_t
+                                 procedureCode_t = 0x6
+                                 criticality_t = 0
+                                 X2SetupFailure
+                                  protocolIEs_t:
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x5
+                                    criticality_t = 0x1
+                                    Cause:
+                                     misc_t = 0x4
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x11
+                                    criticality_t = 0x1
+                                    CriticalityDiagnostics
+                                     procedureCode_t = 0x21
                        */
                        packedPdu: "4006000e0000020005400168001140024021"},
 
                {
                        response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED ",
                        /*
-                       E2AP-PDU:
-                        unsuccessfulOutcome_t
-                         procedureCode_t = 0x6
-                         criticality_t = 0
-                         X2SetupFailure
-                          protocolIEs_t:
-                           ProtocolIE_Container_elm
-                            id_t = 0x5
-                            criticality_t = 0x1
-                            Cause:
-                             misc_t = 0x4
+                               E2AP-PDU:
+                                unsuccessfulOutcome_t
+                                 procedureCode_t = 0x6
+                                 criticality_t = 0
+                                 X2SetupFailure
+                                  protocolIEs_t:
+                                   ProtocolIE_Container_elm
+                                    id_t = 0x5
+                                    criticality_t = 0x1
+                                    Cause:
+                                     misc_t = 0x4
                        */
                        packedPdu: "400600080000010005400168"},
                {
@@ -258,6 +257,8 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                },
        }
 
+       converter := NewX2SetupFailureResponseConverter(logger)
+
        for _, tc := range testCases {
                t.Run(tc.packedPdu, func(t *testing.T) {
 
@@ -267,7 +268,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                                t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
                        }
 
-                       response, err := UnpackX2SetupFailureResponseAndExtract(logger, e2pdus.MaxAsn1CodecAllocationBufferSize /*allocation buffer*/, len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
+                       response, err := converter.UnpackX2SetupFailureResponseAndExtract(payload)
 
                        if err != nil {
                                if tc.failure == nil {
@@ -23,6 +23,7 @@ package converters
 // #include <x2setup_response_wrapper.h>
 import "C"
 import (
+       "e2mgr/e2pdus"
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -40,14 +41,27 @@ const (
        maxnoofNeighbours                = 512
 )
 
+type X2SetupResponseConverter struct {
+       logger *logger.Logger
+}
+
+type IX2SetupResponseConverter interface {
+       UnpackX2SetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Enb, error)
+}
+
+func NewX2SetupResponseConverter(logger *logger.Logger) *X2SetupResponseConverter {
+       return &X2SetupResponseConverter{
+               logger: logger,
+       }
+}
 
 // The following are possible values of a choice field, find which the pdu contains.
 func getENB_ID_choice(eNB_ID C.ENB_ID_t) (entities.EnbType, []byte) {
 
        enbIdAsBitString := (*C.BIT_STRING_t)(unsafe.Pointer(&eNB_ID.choice[0]))
-       switch eNB_ID.present{
+       switch eNB_ID.present {
        case C.ENB_ID_PR_macro_eNB_ID:
-               return entities.EnbType_MACRO_ENB,  C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
+               return entities.EnbType_MACRO_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
        case C.ENB_ID_PR_home_eNB_ID:
                return entities.EnbType_HOME_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
        case C.ENB_ID_PR_short_Macro_eNB_ID:
@@ -70,7 +84,7 @@ func getFDDInfo(fdd *C.FDD_Info_t) (*entities.FddInfo, error) {
 
                extIEs := (*C.ProtocolExtensionContainer_170P145_t)(unsafe.Pointer(fdd.iE_Extensions))
                if extIEs != nil && extIEs.list.count > 0 {
-                       count:= int(extIEs.list.count)
+                       count := int(extIEs.list.count)
                        extIEs_slice := (*[1 << 30]*C.FDD_Info_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
                        for _, member := range extIEs_slice {
                                switch member.extensionValue.present {
@@ -116,7 +130,7 @@ func getAdditionalSpecialSubframeInfo(info *C.AdditionalSpecialSubframe_Info_t)
 }
 
 func getAdditionalSpecialSubframeExtensionInfo(info *C.AdditionalSpecialSubframeExtension_Info_t) *entities.AdditionalSpecialSubframeExtensionInfo {
-       additionalSpecialSubframeExtensionInfo := &entities.AdditionalSpecialSubframeExtensionInfo{AdditionalSpecialSubframePatternsExtension: entities.AdditionalSpecialSubframePatterns_Extension(1 +info.additionalspecialSubframePatternsExtension)}
+       additionalSpecialSubframeExtensionInfo := &entities.AdditionalSpecialSubframeExtensionInfo{AdditionalSpecialSubframePatternsExtension: entities.AdditionalSpecialSubframePatterns_Extension(1 + info.additionalspecialSubframePatternsExtension)}
 
        additionalSpecialSubframeExtensionInfo.CyclicPrefixDl = entities.CyclicPrefix(1 + info.cyclicPrefixDL)
        additionalSpecialSubframeExtensionInfo.CyclicPrefixUl = entities.CyclicPrefix(1 + info.cyclicPrefixUL)
@@ -136,7 +150,7 @@ func getTDDInfo(tdd *C.TDD_Info_t) (*entities.TddInfo, error) {
 
                extIEs := (*C.ProtocolExtensionContainer_170P206_t)(unsafe.Pointer(tdd.iE_Extensions))
                if extIEs != nil && extIEs.list.count > 0 {
-                       count:= int(extIEs.list.count)
+                       count := int(extIEs.list.count)
                        extIEs_slice := (*[1 << 30]*C.TDD_Info_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
                        for _, member := range extIEs_slice {
                                switch member.extensionValue.present {
@@ -171,15 +185,15 @@ func getSubframeAllocation_choice(subframeAllocation C.SubframeAllocation_t) (en
 func getMBSFN_Subframe_Infolist(mBSFN_Subframe_Infolist *C.MBSFN_Subframe_Infolist_t) ([]*entities.MbsfnSubframe, error) {
        var mBSFNSubframes []*entities.MbsfnSubframe
 
-       if mBSFN_Subframe_Infolist.list.count > 0 && mBSFN_Subframe_Infolist.list.count <=  maxnoofMBSFN {
-               count:=int(mBSFN_Subframe_Infolist.list.count)
+       if mBSFN_Subframe_Infolist.list.count > 0 && mBSFN_Subframe_Infolist.list.count <= maxnoofMBSFN {
+               count := int(mBSFN_Subframe_Infolist.list.count)
                BSFN_Subframe_Infolist_slice := (*[1 << 30]*C.MBSFN_Subframe_Info_t)(unsafe.Pointer(mBSFN_Subframe_Infolist.list.array))[:count:count]
                for _, member := range BSFN_Subframe_Infolist_slice {
                        mBSFNSubframe := &entities.MbsfnSubframe{RadioframeAllocationPeriod: entities.RadioframeAllocationPeriod(1 + member.radioframeAllocationPeriod)}
 
                        mBSFNSubframe.RadioframeAllocationOffset = uint32(member.radioframeAllocationOffset)
 
-                       allocType, subframeAllocation, err:= getSubframeAllocation_choice(member.subframeAllocation)
+                       allocType, subframeAllocation, err := getSubframeAllocation_choice(member.subframeAllocation)
                        if err != nil {
                                return nil, err
                        }
@@ -209,8 +223,8 @@ func getPRACHConfiguration(prachConf *C.PRACH_Configuration_t) *entities.PrachCo
 }
 func getServedCellsInfoExt(extIEs *C.ProtocolExtensionContainer_170P192_t, servedCellInfo *entities.ServedCellInfo) error {
 
-       if extIEs != nil && extIEs.list.count > 0  {
-               count:=int(extIEs.list.count)
+       if extIEs != nil && extIEs.list.count > 0 {
+               count := int(extIEs.list.count)
                extIEs_slice := (*[1 << 30]*C.ServedCell_Information_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
                for _, member := range extIEs_slice {
                        switch member.extensionValue.present {
@@ -218,7 +232,7 @@ func getServedCellsInfoExt(extIEs *C.ProtocolExtensionContainer_170P192_t, serve
                                ports := (*C.Number_of_Antennaports_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
                                servedCellInfo.NumberOfAntennaPorts = entities.NumberOfAntennaPorts(1 + *ports)
                        case C.ServedCell_Information_ExtIEs__extensionValue_PR_PRACH_Configuration:
-                               prachConfiguration:= getPRACHConfiguration((*C.PRACH_Configuration_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
+                               prachConfiguration := getPRACHConfiguration((*C.PRACH_Configuration_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
                                servedCellInfo.PrachConfiguration = prachConfiguration
                        case C.ServedCell_Information_ExtIEs__extensionValue_PR_MBSFN_Subframe_Infolist:
                                mBSFN_Subframe_Infolist, err := getMBSFN_Subframe_Infolist((*C.MBSFN_Subframe_Infolist_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
@@ -228,20 +242,20 @@ func getServedCellsInfoExt(extIEs *C.ProtocolExtensionContainer_170P192_t, serve
                                servedCellInfo.MbsfnSubframeInfos = mBSFN_Subframe_Infolist
                        case C.ServedCell_Information_ExtIEs__extensionValue_PR_CSG_Id:
                                csgId := (*C.CSG_Id_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
-                               servedCellInfo.CsgId =  fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(csgId.buf), C.int(csgId.size)))
+                               servedCellInfo.CsgId = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(csgId.buf), C.int(csgId.size)))
                        case C.ServedCell_Information_ExtIEs__extensionValue_PR_MBMS_Service_Area_Identity_List:
                                mBMS_Service_Area_Identity_List := (*C.MBMS_Service_Area_Identity_List_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
                                if mBMS_Service_Area_Identity_List.list.count > 0 && mBMS_Service_Area_Identity_List.list.count < maxnoofMBMSServiceAreaIdentities {
-                                       count:= int(mBMS_Service_Area_Identity_List.list.count)
+                                       count := int(mBMS_Service_Area_Identity_List.list.count)
                                        mBMS_Service_Area_Identity_List_slice := (*[1 << 30]*C.MBMS_Service_Area_Identity_t)(unsafe.Pointer(mBMS_Service_Area_Identity_List.list.array))[:count:count]
                                        for _, identity := range mBMS_Service_Area_Identity_List_slice {
-                                               servedCellInfo.MbmsServiceAreaIdentities = append(servedCellInfo.MbmsServiceAreaIdentities, fmt.Sprintf("%02x",C.GoBytes(unsafe.Pointer(identity.buf), C.int(identity.size))))
+                                               servedCellInfo.MbmsServiceAreaIdentities = append(servedCellInfo.MbmsServiceAreaIdentities, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(identity.buf), C.int(identity.size))))
                                        }
                                }
                        case C.ServedCell_Information_ExtIEs__extensionValue_PR_MultibandInfoList:
                                multibandInfoList := (*C.MultibandInfoList_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
                                if multibandInfoList.list.count > 0 && multibandInfoList.list.count < maxnoofBands {
-                                       count:= int(multibandInfoList.list.count)
+                                       count := int(multibandInfoList.list.count)
                                        multibandInfoList_slice := (*[1 << 30]*C.BandInfo_t)(unsafe.Pointer(multibandInfoList.list.array))[:count:count]
                                        for _, bandInfo := range multibandInfoList_slice {
                                                servedCellInfo.MultibandInfos = append(servedCellInfo.MultibandInfos, uint32(bandInfo.freqBandIndicator))
@@ -265,11 +279,11 @@ func getServedCellsInfoExt(extIEs *C.ProtocolExtensionContainer_170P192_t, serve
        return nil
 }
 
-func getServedCellsNeighbour_Info(neighbour_Information*C.Neighbour_Information_t) ([]*entities.NeighbourInformation, error) {
+func getServedCellsNeighbour_Info(neighbour_Information *C.Neighbour_Information_t) ([]*entities.NeighbourInformation, error) {
        var neighbours []*entities.NeighbourInformation
 
        if neighbour_Information != nil && neighbour_Information.list.count > 0 && neighbour_Information.list.count <= maxnoofNeighbours {
-               count:= int(neighbour_Information.list.count)
+               count := int(neighbour_Information.list.count)
                neighbour_Information_slice := (*[1 << 30]*C.Neighbour_Information__Member)(unsafe.Pointer(neighbour_Information.list.array))[:count:count]
                for _, member := range neighbour_Information_slice {
 
@@ -278,13 +292,13 @@ func getServedCellsNeighbour_Info(neighbour_Information*C.Neighbour_Information_
                        eUTRANcellIdentifier := C.GoBytes(unsafe.Pointer(member.eCGI.eUTRANcellIdentifier.buf), C.int(member.eCGI.eUTRANcellIdentifier.size))
                        neighbourInfo := &entities.NeighbourInformation{Ecgi: fmt.Sprintf("%02x:%02x", plmnId, eUTRANcellIdentifier)}
 
-                       neighbourInfo.Pci  = uint32(member.pCI)
+                       neighbourInfo.Pci = uint32(member.pCI)
 
                        neighbourInfo.EarFcn = uint32(member.eARFCN)
 
-                       extIEs:= (*C.ProtocolExtensionContainer_170P172_t)(unsafe.Pointer(member.iE_Extensions))
+                       extIEs := (*C.ProtocolExtensionContainer_170P172_t)(unsafe.Pointer(member.iE_Extensions))
                        if extIEs != nil && extIEs.list.count > 0 {
-                               count:= int(extIEs.list.count)
+                               count := int(extIEs.list.count)
                                neighbour_Information_ExtIEs_slice := (*[1 << 30]*C.Neighbour_Information_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
                                for _, neighbour_Information_ExtIE := range neighbour_Information_ExtIEs_slice {
                                        switch neighbour_Information_ExtIE.extensionValue.present {
@@ -298,7 +312,7 @@ func getServedCellsNeighbour_Info(neighbour_Information*C.Neighbour_Information_
                                }
                        }
 
-                       neighbours = append(neighbours,neighbourInfo)
+                       neighbours = append(neighbours, neighbourInfo)
                }
        }
 
@@ -308,8 +322,8 @@ func getServedCellsNeighbour_Info(neighbour_Information*C.Neighbour_Information_
 func getServedCells(servedCellsIE *C.ServedCells_t) ([]*entities.ServedCellInfo, error) {
        var servedCells []*entities.ServedCellInfo
 
-       if servedCellsIE != nil && servedCellsIE.list.count > 0 && servedCellsIE.list.count  < maxCellineNB {
-               count:= int(servedCellsIE.list.count)
+       if servedCellsIE != nil && servedCellsIE.list.count > 0 && servedCellsIE.list.count < maxCellineNB {
+               count := int(servedCellsIE.list.count)
                servedCells__Member_slice := (*[1 << 30]*C.ServedCells__Member)(unsafe.Pointer(servedCellsIE.list.array))[:count:count]
                for _, member := range servedCells__Member_slice {
                        servedCellInfo := &entities.ServedCellInfo{Pci: uint32(member.servedCellInfo.pCI)}
@@ -366,7 +380,7 @@ func getGUGroupIDList(guGroupIDList *C.GUGroupIDList_t) []string {
        var ids []string
 
        if guGroupIDList != nil && guGroupIDList.list.count > 0 && guGroupIDList.list.count <= maxPools {
-               count:=int(guGroupIDList.list.count)
+               count := int(guGroupIDList.list.count)
                guGroupIDList_slice := (*[1 << 30]*C.GU_Group_ID_t)(unsafe.Pointer(guGroupIDList.list.array))[:count:count]
                for _, guGroupID := range guGroupIDList_slice {
                        plmnId := C.GoBytes(unsafe.Pointer(guGroupID.pLMN_Identity.buf), C.int(guGroupID.pLMN_Identity.size))
@@ -398,7 +412,7 @@ func x2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *entiti
                                        case C.X2SetupResponse_IEs__value_PR_GlobalENB_ID:
                                                globalENB_ID := (*C.GlobalENB_ID_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0]))
                                                plmnId := C.GoBytes(unsafe.Pointer(globalENB_ID.pLMN_Identity.buf), C.int(globalENB_ID.pLMN_Identity.size))
-                                               enbType, enbVal:= getENB_ID_choice(globalENB_ID.eNB_ID)
+                                               enbType, enbVal := getENB_ID_choice(globalENB_ID.eNB_ID)
 
                                                globalNbId = &entities.GlobalNbId{}
                                                globalNbId.NbId = fmt.Sprintf("%02x", enbVal)
@@ -412,7 +426,7 @@ func x2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *entiti
                                                }
                                                enb.ServedCells = ServedCells
                                        case C.X2SetupResponse_IEs__value_PR_GUGroupIDList:
-                                               enb.GuGroupIds= getGUGroupIDList((*C.GUGroupIDList_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0])))
+                                               enb.GuGroupIds = getGUGroupIDList((*C.GUGroupIDList_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0])))
                                        case C.X2SetupResponse_IEs__value_PR_CriticalityDiagnostics:
                                                /*ignored*/
                                        case C.X2SetupResponse_IEs__value_PR_LHN_ID:
@@ -423,12 +437,11 @@ func x2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *entiti
                }
        }
 
-
        return globalNbId, &enb, nil
 }
 
-func UnpackX2SetupResponseAndExtract(logger *logger.Logger, allocationBufferSize int, packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (*entities.GlobalNbId, *entities.Enb, error) {
-       pdu, err := UnpackX2apPdu(logger, allocationBufferSize, packedBufferSize, packedBuf, maxMessageBufferSize)
+func (c *X2SetupResponseConverter) UnpackX2SetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Enb, error) {
+       pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
        if err != nil {
                return nil, nil, err
        }
@@ -436,4 +449,3 @@ func UnpackX2SetupResponseAndExtract(logger *logger.Logger, allocationBufferSize
        defer C.delete_pdu(pdu)
        return x2SetupResponseToProtobuf(pdu)
 }
-
@@ -18,7 +18,6 @@
 package converters
 
 import (
-       "e2mgr/e2pdus"
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -28,7 +27,7 @@ import (
 
 /*
 Test permutations of x2 setup response to protobuf enb
- */
+*/
 
 func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
        logger, _ := logger.InitLogger(logger.InfoLevel)
@@ -1146,6 +1145,8 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        /*failure: fmt.Errorf("getAtom for path [successfulOutcome_t X2SetupResponse protocolIEs_t ProtocolIE_Container_elm GlobalENB-ID pLMN_Identity_t] failed, rc = 2" /NO_SPACE_LEFT),*/ },
        }
 
+       converter := NewX2SetupResponseConverter(logger)
+
        for _, tc := range testCases {
                t.Run(tc.packedPdu, func(t *testing.T) {
 
@@ -1155,7 +1156,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                                t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
                        }
 
-                       key, enb, err := UnpackX2SetupResponseAndExtract(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
+                       key, enb, err := converter.UnpackX2SetupResponseAndExtract(payload)
 
                        if err != nil {
                                if tc.failure == nil {
index cd0cb37..7116785 100644 (file)
@@ -27,7 +27,7 @@ func NewWrongStateError(activityName string, state string) *WrongStateError {
        return &WrongStateError{
                &BaseError{
                        Code:    403,
-                       Message: fmt.Sprintf("Activity <%s> rejected. RAN current state <%s> does not allow its execution ", activityName, state) ,
+                       Message: fmt.Sprintf("Activity %s rejected. RAN current state %s does not allow its execution ", activityName, state) ,
                },
        }
 }
diff --git a/E2Manager/enums/message_direction.go b/E2Manager/enums/message_direction.go
new file mode 100644 (file)
index 0000000..6697e13
--- /dev/null
@@ -0,0 +1,39 @@
+package enums
+
+import (
+       "encoding/json"
+       "strconv"
+)
+
+type MessageDirection int32
+
+var messageDirectionEnumName = map[int32]string{
+       0: "UNKNOWN_MESSAGE_DIRECTION",
+       1: "RAN_TO_RIC",
+       2: "RIC_TO_RAN",
+}
+
+const (
+       UNKNOWN_MESSAGE_DIRECTION MessageDirection = 0
+       RAN_TO_RIC                MessageDirection = 1
+       RIC_TO_RAN                MessageDirection = 2
+)
+
+func (md MessageDirection) String() string {
+       s, ok := messageDirectionEnumName[int32(md)]
+       if ok {
+               return s
+       }
+       return strconv.Itoa(int(md))
+}
+
+func (md MessageDirection) MarshalJSON() ([]byte, error) {
+       _, ok := messageDirectionEnumName[int32(md)]
+
+       if !ok {
+               return nil,&json.UnsupportedValueError{}
+       }
+
+       v:= int32(md)
+       return json.Marshal(v)
+}
index 5be855c..6576a0b 100644 (file)
@@ -1,26 +1,10 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.19 h1:b6ggNQ4PdWxCkQupfus80nsCs0YD84u+cGc+nQ2W560=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.19/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.21 h1:eK9nUZOTMJ/EnMpH9bkWtMgOvCn3u4+PNCb9gu10s6w=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.21/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23 h1:JbSOhvj9fVEUF2XZg8cw5QAyeKUi5xXgpwXrrxfDgLM=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.19 h1:5VGHtsiGnR/VfcsqhbKVScUTLBgoePp1KhSVylwlFKM=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.19/go.mod h1:GXiXLz4ORBeIr0FLIbzENRykgh3Po5uPkX2jICxnRF0=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.21 h1:PQ/Mu2ol+8Oh/0BqCWWhPlVVoRCg5dQDEGm4+Opp5w4=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.21/go.mod h1:GXiXLz4ORBeIr0FLIbzENRykgh3Po5uPkX2jICxnRF0=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23 h1:akVZc8NWJ9oPujd7cQY3Ti3se4PF1/NoC+Dwt+YzINc=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23/go.mod h1:GXiXLz4ORBeIr0FLIbzENRykgh3Po5uPkX2jICxnRF0=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.19 h1:WwUWG3mp2uU9ouqAzj4d6dUGZUA+2HmutQBiH4s4UIw=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.19/go.mod h1:7fQ7/R9hBsCi5g6444ySaavYLB+/aCsCyDEiqWK+L34=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.21 h1:N3UbqJ9WqC8JEz/TwHHwZwCFAW6VTlZLpD5lnbdD+Y8=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.21/go.mod h1:SQBZLy1HP94i1vQ3y730wGFsrHqZtgPaEkzPgtqBNw0=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23 h1:TYV3HE2UNwGOWiA4C226/WhB94crwjuHKIFTgDDvo8I=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23/go.mod h1:uZVjwZjfWV4JJzyQVO/O48Ykph57zfpfMB7nK+WGKX8=
-gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.2.0 h1:7edCLIQtk9xCwxTtLRUlXr8wQ6nmr/Mo4ZoqjF3m0NE=
-gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.2.0/go.mod h1:2Y8gw2jqj9urI8VFqFQn7BX0J3A852+YrXVV9V8gOt4=
-gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.0 h1:Gg3PH9XVAuSjyAr8Z8Ebmcmt6PTKeU/+FG6J7qQl+ew=
-gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.0/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
 gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.1 h1:ZIhABs0WLMn8lp1Y3719315/3jbV+yLcovOGScL03eM=
 gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.1/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
@@ -53,8 +37,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-ozzo/ozzo-validation v3.5.0+incompatible h1:sUy/in/P6askYr16XJgTKq/0SZhiWsdg4WZGaLsGQkM=
 github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
-github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
-github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-redis/redis v6.15.3+incompatible h1:NZ0O90AhLSvSrvLZ/S9h7D4kl1mW2PrKyxL7MyBKO2g=
 github.com/go-redis/redis v6.15.3+incompatible/go.mod h1:W2YCLaZryXHirdd9QqwkiVUxCQsrx8SbLq9Uqk7JS7A=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
index ba77075..fc6b3c4 100644 (file)
@@ -25,6 +25,7 @@ import (
        "e2mgr/models"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "e2mgr/stateMachine"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "time"
@@ -32,36 +33,35 @@ import (
 
 type DeleteAllRequestHandler struct {
        rnibDataService services.RNibDataService
-       rmrService *services.RmrService
-       config *configuration.Configuration
-       logger         *logger.Logger
+       rmrSender       *rmrsender.RmrSender
+       config          *configuration.Configuration
+       logger          *logger.Logger
 }
 
-func NewDeleteAllRequestHandler(logger *logger.Logger, rmrService *services.RmrService, config *configuration.Configuration, rnibDataService services.RNibDataService) *DeleteAllRequestHandler {
+func NewDeleteAllRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rnibDataService services.RNibDataService) *DeleteAllRequestHandler {
        return &DeleteAllRequestHandler{
-               logger:         logger,
+               logger:          logger,
                rnibDataService: rnibDataService,
-               rmrService:     rmrService,
-               config:         config,
+               rmrSender:       rmrSender,
+               config:          config,
        }
 }
 
-func (handler *DeleteAllRequestHandler) Handle(request models.Request) error {
+func (handler *DeleteAllRequestHandler) Handle(request models.Request) (models.IResponse, error) {
 
        err, continueFlow := handler.updateNodebStates(false)
        if err != nil {
-               return err
+               return nil, err
        }
 
        if continueFlow == false {
-               return nil
+               return nil, nil
        }
 
-       //TODO change to rmr_request
-       response := models.NotificationResponse{MgsType: rmrCgo.RIC_SCTP_CLEAR_ALL}
-       if err := handler.rmrService.SendRmrMessage(&response); err != nil {
+       response := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
+       if err := handler.rmrSender.Send(&response); err != nil {
                handler.logger.Errorf("#DeleteAllRequestHandler.Handle - failed to send sctp clear all message to RMR: %s", err)
-               return e2managererrors.NewRmrError()
+               return nil, e2managererrors.NewRmrError()
        }
 
        time.Sleep(time.Duration(handler.config.BigRedButtonTimeoutSec) * time.Second)
@@ -69,10 +69,10 @@ func (handler *DeleteAllRequestHandler) Handle(request models.Request) error {
 
        err, _ = handler.updateNodebStates(true)
        if err != nil {
-               return err
+               return nil, err
        }
 
-       return nil
+       return nil, nil
 }
 
 func (handler *DeleteAllRequestHandler) updateNodebStates(timeoutExpired bool) (error, bool) {
index 6e16766..3f8423d 100644 (file)
@@ -22,10 +22,10 @@ import (
        "e2mgr/e2managererrors"
        "e2mgr/logger"
        "e2mgr/mocks"
-       "e2mgr/models"
        "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
@@ -54,28 +54,28 @@ func setupTest(t *testing.T) (*logger.Logger, *configuration.Configuration, *moc
        return log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock
 }
 
-func TestHandleBeforeTimerGetListNodebIdsFailedFlow(t *testing.T){
+func TestHandleBeforeTimerGetListNodebIdsFailedFlow(t *testing.T) {
        log, config, readerMock, _, rnibDataService, rmrMessengerMock := setupTest(t)
 
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        rnibErr := &common.ResourceNotFoundError{}
        var nbIdentityList []*entities.NbIdentity
        readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr)
 
        expected := &e2managererrors.RnibDbError{}
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
                t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
        }
 }
 
-func TestHandleAfterTimerGetListNodebIdsFailedFlow(t *testing.T){
+func TestHandleAfterTimerGetListNodebIdsFailedFlow(t *testing.T) {
        log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t)
 
        config.BigRedButtonTimeoutSec = 1
 
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        rnibErr := &common.ResourceNotFoundError{}
        //Before timer: Disconnected->ShutDown, ShuttingDown->Ignore, Connected->ShuttingDown
@@ -96,18 +96,18 @@ func TestHandleAfterTimerGetListNodebIdsFailedFlow(t *testing.T){
        writerMock.On("SaveNodeb", mock.Anything, updatedNb3).Return(nil)
 
        expected := &e2managererrors.RnibDbError{}
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
 
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
                t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
        }
 }
 
-func TestHandleSuccessFlow(t *testing.T){
+func TestHandleSuccessFlow(t *testing.T) {
        log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t)
 
        config.BigRedButtonTimeoutSec = 1
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        //Before timer: Disconnected->ShutDown, ShuttingDown->Ignore, Connected->ShuttingDown
        nbIdentityList := createIdentityList()
@@ -141,18 +141,18 @@ func TestHandleSuccessFlow(t *testing.T){
        writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(nil)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), tests.MaxMsgSize).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
 
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
 
        assert.Nil(t, actual)
 }
 
-func TestHandleSuccessGetNextStatusFlow(t *testing.T){
+func TestHandleSuccessGetNextStatusFlow(t *testing.T) {
        log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t)
 
        config.BigRedButtonTimeoutSec = 1
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
        readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
@@ -173,18 +173,18 @@ func TestHandleSuccessGetNextStatusFlow(t *testing.T){
        writerMock.On("SaveNodeb", mock.Anything, updatedNb1AfterTimer).Return(nil)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), tests.MaxMsgSize).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
 
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
 
        assert.Nil(t, actual)
 }
 
-func TestHandleShuttingDownStatusFlow(t *testing.T){
+func TestHandleShuttingDownStatusFlow(t *testing.T) {
        log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t)
 
        config.BigRedButtonTimeoutSec = 1
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
        readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
@@ -202,18 +202,18 @@ func TestHandleShuttingDownStatusFlow(t *testing.T){
        writerMock.On("SaveNodeb", mock.Anything, updatedNb1AfterTimer).Return(nil)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), tests.MaxMsgSize).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
 
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
 
        assert.Nil(t, actual)
 }
 
-func TestHandleGetNodebFailedFlow(t *testing.T){
+func TestHandleGetNodebFailedFlow(t *testing.T) {
        log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t)
 
        config.BigRedButtonTimeoutSec = 1
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        //Before timer: Disconnected->ShutDown(will fail), ShuttingDown->Ignore, Connected->ShuttingDown
        nbIdentityList := createIdentityList()
@@ -248,18 +248,18 @@ func TestHandleGetNodebFailedFlow(t *testing.T){
        writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(nil)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), tests.MaxMsgSize).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
 
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
 
        assert.Nil(t, actual)
 }
 
-func TestHandleSaveFailedFlow(t *testing.T){
+func TestHandleSaveFailedFlow(t *testing.T) {
        log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t)
 
        config.BigRedButtonTimeoutSec = 1
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        //Before timer: Disconnected->ShutDown, ShuttingDown->Ignore, Connected->ShuttingDown(will fail)
        nbIdentityList := createIdentityList()
@@ -294,18 +294,18 @@ func TestHandleSaveFailedFlow(t *testing.T){
        writerMock.On("SaveNodeb", mock.Anything, updatedNb3AfterTimer).Return(errRnib)
 
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), tests.MaxMsgSize).Return(mbuf, nil)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, nil)
 
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
 
        assert.Nil(t, actual)
 }
 
-func TestHandleSendRmrFailedFlow(t *testing.T){
+func TestHandleSendRmrFailedFlow(t *testing.T) {
        log, config, readerMock, writerMock, rnibDataService, rmrMessengerMock := setupTest(t)
 
        config.BigRedButtonTimeoutSec = 1
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        //Before timer: Disconnected->ShutDown, ShuttingDown->Ignore, Connected->ShuttingDown(will fail)
        nbIdentityList := createIdentityList()
@@ -340,26 +340,26 @@ func TestHandleSendRmrFailedFlow(t *testing.T){
 
        expected := e2managererrors.NewRmrError()
        mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize, "RanName", &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), tests.MaxMsgSize).Return(mbuf, expected)
+       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf))).Return(mbuf, expected)
 
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
 
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
                t.Errorf("Error actual = %v, and Expected = %v.", actual, expected)
        }
 }
 
-func TestHandleGetListEnbIdsEmptyFlow(t *testing.T){
+func TestHandleGetListEnbIdsEmptyFlow(t *testing.T) {
        log, config, readerMock, _, rnibDataService, rmrMessengerMock := setupTest(t)
 
-       handler := NewDeleteAllRequestHandler(log, getRmrService(rmrMessengerMock, log), config, rnibDataService)
+       handler := NewDeleteAllRequestHandler(log, getRmrSender(rmrMessengerMock, log), config, rnibDataService)
 
        var rnibError error
        nbIdentityList := []*entities.NbIdentity{}
 
        readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError)
 
-       actual := handler.Handle(nil)
+       _, actual := handler.Handle(nil)
        readerMock.AssertNumberOfCalls(t, "GetNodeb", 0)
        assert.Nil(t, actual)
 }
@@ -385,9 +385,8 @@ func initLog(t *testing.T) *logger.Logger {
        return log
 }
 
-func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService {
+func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       messageChannel := make(chan *models.NotificationResponse)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, messageChannel)
+       return rmrsender.NewRmrSender(log, &rmrMessenger)
 }
diff --git a/E2Manager/handlers/httpmsghandlers/get_nodeb_id_list_request_handler.go b/E2Manager/handlers/httpmsghandlers/get_nodeb_id_list_request_handler.go
new file mode 100644 (file)
index 0000000..598e672
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package httpmsghandlers
+
+import (
+       "e2mgr/e2managererrors"
+       "e2mgr/logger"
+       "e2mgr/models"
+       "e2mgr/services"
+)
+
+type GetNodebIdListRequestHandler struct {
+       rNibDataService services.RNibDataService
+       logger          *logger.Logger
+}
+
+func NewGetNodebIdListRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *GetNodebIdListRequestHandler {
+       return &GetNodebIdListRequestHandler{
+               logger:          logger,
+               rNibDataService: rNibDataService,
+       }
+}
+
+func (handler *GetNodebIdListRequestHandler) Handle(request models.Request) (models.IResponse, error) {
+
+       nodebIdList, err := handler.rNibDataService.GetListNodebIds()
+
+       if err != nil {
+               handler.logger.Errorf("#GetNodebIdListRequestHandler.Handle - Error fetching Nodeb Identity list from rNib: %v", err)
+               return nil, e2managererrors.NewRnibDbError()
+       }
+
+       return models.NewGetNodebIdListResponse(nodebIdList), nil
+}
diff --git a/E2Manager/handlers/httpmsghandlers/get_nodeb_id_list_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/get_nodeb_id_list_request_handler_test.go
new file mode 100644 (file)
index 0000000..f9b630c
--- /dev/null
@@ -0,0 +1,62 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package httpmsghandlers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/mocks"
+       "e2mgr/models"
+       "e2mgr/services"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
+       "github.com/pkg/errors"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func setupGetNodebIdListRequestHandlerTest(t *testing.T) (*GetNodebIdListRequestHandler, *mocks.RnibReaderMock) {
+       log := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+       readerMock := &mocks.RnibReaderMock{}
+       readerProvider := func() reader.RNibReader {
+               return readerMock
+       }
+       rnibDataService := services.NewRnibDataService(log, config, readerProvider, nil)
+       handler := NewGetNodebIdListRequestHandler(log, rnibDataService)
+       return handler, readerMock
+}
+
+func TestHandleGetNodebIdListSuccess(t *testing.T) {
+       handler, readerMock := setupGetNodebIdListRequestHandlerTest(t)
+       var rnibError error
+       readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, rnibError)
+       response, err := handler.Handle(nil)
+       assert.Nil(t, err)
+       assert.NotNil(t, response)
+       assert.IsType(t, &models.GetNodebIdListResponse{}, response)
+}
+
+func TestHandleGetNodebIdListFailure(t *testing.T) {
+       handler, readerMock := setupGetNodebIdListRequestHandlerTest(t)
+       var nodebIdList []*entities.NbIdentity
+       readerMock.On("GetListNodebIds").Return(nodebIdList, common.NewInternalError(errors.New("#reader.GetListNodebIds - Internal Error")))
+       response, err := handler.Handle(nil)
+       assert.NotNil(t, err)
+       assert.Nil(t, response)
+}
diff --git a/E2Manager/handlers/httpmsghandlers/get_nodeb_request_handler.go b/E2Manager/handlers/httpmsghandlers/get_nodeb_request_handler.go
new file mode 100644 (file)
index 0000000..0c9a7ba
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package httpmsghandlers
+
+import (
+       "e2mgr/e2managererrors"
+       "e2mgr/logger"
+       "e2mgr/models"
+       "e2mgr/services"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+)
+
+type GetNodebRequestHandler struct {
+       rNibDataService services.RNibDataService
+       logger          *logger.Logger
+}
+
+func NewGetNodebRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *GetNodebRequestHandler {
+       return &GetNodebRequestHandler{
+               logger:          logger,
+               rNibDataService: rNibDataService,
+       }
+}
+
+func (handler *GetNodebRequestHandler) Handle(request models.Request) (models.IResponse, error) {
+       getNodebRequest := request.(models.GetNodebRequest)
+       ranName:= getNodebRequest.RanName
+       nodeb, err := handler.rNibDataService.GetNodeb(ranName)
+
+       if err != nil {
+               handler.logger.Errorf("#GetNodebRequestHandler.Handle - RAN name: %s - Error fetching RAN from rNib: %v",  ranName, err)
+               return nil, rnibErrorToE2ManagerError(err)
+       }
+
+       return models.NewGetNodebResponse(nodeb), nil
+}
+
+func rnibErrorToE2ManagerError(err error) error {
+       _, ok := err.(*common.ResourceNotFoundError)
+       if ok {
+               return e2managererrors.NewResourceNotFoundError()
+       }
+       return e2managererrors.NewRnibDbError()
+}
diff --git a/E2Manager/handlers/httpmsghandlers/get_nodeb_request_handler_test.go b/E2Manager/handlers/httpmsghandlers/get_nodeb_request_handler_test.go
new file mode 100644 (file)
index 0000000..c679988
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package httpmsghandlers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/mocks"
+       "e2mgr/models"
+       "e2mgr/services"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
+       "github.com/pkg/errors"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func setupGetNodebRequestHandlerTest(t *testing.T) (*GetNodebRequestHandler, *mocks.RnibReaderMock) {
+       log := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+       readerMock := &mocks.RnibReaderMock{}
+       readerProvider := func() reader.RNibReader {
+               return readerMock
+       }
+       rnibDataService := services.NewRnibDataService(log, config, readerProvider, nil)
+       handler := NewGetNodebRequestHandler(log, rnibDataService)
+       return handler, readerMock
+}
+
+func TestHandleGetNodebSuccess(t *testing.T) {
+       handler, readerMock := setupGetNodebRequestHandlerTest(t)
+
+       ranName := "test1"
+       var rnibError error
+       readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{RanName:ranName}, rnibError)
+       response, err := handler.Handle(models.GetNodebRequest{RanName: ranName})
+       assert.Nil(t, err)
+       assert.NotNil(t, response)
+       assert.IsType(t, &models.GetNodebResponse{}, response)
+}
+
+func TestHandleGetNodebFailure(t *testing.T) {
+       handler, readerMock := setupGetNodebRequestHandlerTest(t)
+       ranName := "test1"
+       var nodebInfo *entities.NodebInfo
+       readerMock.On("GetNodeb", ranName).Return(nodebInfo, common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")))
+       response, err := handler.Handle(models.GetNodebRequest{RanName: ranName})
+       assert.NotNil(t, err)
+       assert.Nil(t, response)
+}
index 7bf6f1e..2fc4d60 100644 (file)
@@ -22,5 +22,5 @@ import (
 )
 
 type RequestHandler interface {
-       Handle(request models.Request) error
+       Handle(request models.Request) (models.IResponse, error)
 }
index 36df7bf..ebdc1be 100644 (file)
@@ -51,13 +51,13 @@ func NewSetupRequestHandler(logger *logger.Logger, rNibDataService services.RNib
        }
 }
 
-func (handler *SetupRequestHandler) Handle(request models.Request) error {
+func (handler *SetupRequestHandler) Handle(request models.Request) (models.IResponse, error) {
 
        setupRequest := request.(models.SetupRequest)
 
        err := handler.validateRequestDetails(setupRequest)
        if err != nil {
-               return err
+               return nil, err
        }
 
        nodebInfo, err := handler.rNibDataService.GetNodeb(setupRequest.RanName)
@@ -66,15 +66,15 @@ func (handler *SetupRequestHandler) Handle(request models.Request) error {
                if !ok {
                        handler.logger.Errorf("#SetupRequestHandler.Handle - failed to get nodeB entity for ran name: %v from RNIB. Error: %s",
                                setupRequest.RanName, err.Error())
-                       return e2managererrors.NewRnibDbError()
+                       return nil, e2managererrors.NewRnibDbError()
                }
 
                result := handler.connectNewRan(&setupRequest, handler.protocol)
-               return result
+               return nil, result
        }
 
        result := handler.connectExistingRan(nodebInfo)
-       return result
+       return nil, result
 }
 
 func (handler *SetupRequestHandler) connectExistingRan(nodebInfo *entities.NodebInfo) error {
index a545cff..fc3d075 100644 (file)
@@ -17,6 +17,7 @@
 package httpmsghandlers
 
 import (
+       "e2mgr/rnibBuilders"
        "e2mgr/configuration"
        "e2mgr/e2managererrors"
        "e2mgr/e2pdus"
@@ -25,7 +26,6 @@ import (
        "e2mgr/models"
        "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
-       "e2mgr/rnibBuilders"
        "e2mgr/services"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -57,9 +57,9 @@ func TestSetupHandleNewRanSave_Error(t *testing.T) {
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
        expected := &e2managererrors.RnibDbError{}
 
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
@@ -91,9 +91,9 @@ func TestSetupHandleNewRan_Success(t *testing.T) {
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        assert.Nil(t, actual)
 
@@ -120,10 +120,10 @@ func TestEndcSetupHandleRmr_Error(t *testing.T) {
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
 
        rmrErr := &e2managererrors.RmrError{}
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, rmrErr)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, rmrErr)
 
        sr := models.SetupRequest{"127.0.0.1", 8080, ranName,}
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        if reflect.TypeOf(actual) != reflect.TypeOf(rmrErr) {
                t.Errorf("Error actual = %v, and Expected = %v.", actual, rmrErr)
@@ -147,10 +147,10 @@ func TestEndcSetupHandleExistingDisconnectedRan_Success(t *testing.T) {
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
        sr := models.SetupRequest{"127.0.0.1", 8080, ranName,}
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        assert.Nil(t, actual)
 
@@ -175,7 +175,7 @@ func TestX2SetupHandleExistingConnectedRan_Success(t *testing.T) {
        rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
 
        sr := models.SetupRequest{"127.0.0.1", 8080, ranName,}
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        assert.Nil(t, actual)
 
@@ -184,14 +184,14 @@ func TestX2SetupHandleExistingConnectedRan_Success(t *testing.T) {
 }
 
 func TestX2SetupHandleRnibGet_Error(t *testing.T) {
-       readerMock, _, handler,rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
+       readerMock, _, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
 
        rnibErr := &common.ValidationError{}
        nb := &entities.NodebInfo{RanName: "RanName", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
        readerMock.On("GetNodeb", "RanName").Return(nb, rnibErr)
 
        sr := models.SetupRequest{"127.0.0.1", 8080, "RanName",}
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        expected := &e2managererrors.RnibDbError{}
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
@@ -207,7 +207,7 @@ func TestX2SetupHandleShuttingDownRan_Error(t *testing.T) {
        readerMock.On("GetNodeb", "RanName").Return(nb, nil)
 
        sr := models.SetupRequest{"127.0.0.1", 8080, "RanName",}
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        expected := &e2managererrors.WrongStateError{}
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
@@ -221,7 +221,7 @@ func TestX2SetupHandleNoPort_Error(t *testing.T) {
        _, writerMock, handler, rmrMessengerMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
 
        sr := models.SetupRequest{"127.0.0.1", 0, "RanName",}
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        expected := &e2managererrors.RequestValidationError{}
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
@@ -238,7 +238,7 @@ func TestX2SetupHandleNoRanName_Error(t *testing.T) {
        sr.RanPort = 8080
        sr.RanIp = "127.0.0.1"
 
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        expected := &e2managererrors.RequestValidationError{}
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
@@ -255,7 +255,7 @@ func TestX2SetupHandleNoIP_Error(t *testing.T) {
        sr.RanPort = 8080
        sr.RanName = "RanName"
 
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        expected := &e2managererrors.RequestValidationError{}
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
@@ -273,7 +273,7 @@ func TestX2SetupHandleInvalidIp_Error(t *testing.T) {
        sr.RanName = "RanName"
        sr.RanIp = "invalid ip"
 
-       actual := handler.Handle(sr)
+       _, actual := handler.Handle(sr)
 
        expected := &e2managererrors.RequestValidationError{}
        if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
@@ -283,7 +283,7 @@ func TestX2SetupHandleInvalidIp_Error(t *testing.T) {
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
 }
 
-func initSetupRequestTest(t *testing.T, protocol entities.E2ApplicationProtocol)(*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.RmrMessengerMock) {
+func initSetupRequestTest(t *testing.T, protocol entities.E2ApplicationProtocol) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.RmrMessengerMock) {
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
@@ -297,12 +297,12 @@ func initSetupRequestTest(t *testing.T, protocol entities.E2ApplicationProtocol)
        }
 
        rmrMessengerMock := &mocks.RmrMessengerMock{}
-       rmrService := getRmrService(rmrMessengerMock, log)
+       rmrSender := getRmrSender(rmrMessengerMock, log)
 
        rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
 
-       ranSetupManager := managers.NewRanSetupManager(log, rmrService, rnibDataService)
+       ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
        handler := NewSetupRequestHandler(log, rnibDataService, ranSetupManager, protocol)
 
        return readerMock, writerMock, handler, rmrMessengerMock
-}
\ No newline at end of file
+}
index 3d02272..755984e 100644 (file)
@@ -24,6 +24,7 @@ import (
        "e2mgr/models"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
@@ -34,51 +35,59 @@ const (
 
 type X2ResetRequestHandler struct {
        rNibDataService services.RNibDataService
-       rmrService     *services.RmrService
-       logger         *logger.Logger
+       rmrSender       *rmrsender.RmrSender
+       logger          *logger.Logger
 }
 
-func NewX2ResetRequestHandler(logger *logger.Logger, rmrService *services.RmrService, rNibDataService services.RNibDataService) *X2ResetRequestHandler {
+func NewX2ResetRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService) *X2ResetRequestHandler {
        return &X2ResetRequestHandler{
                rNibDataService: rNibDataService,
-               rmrService:     rmrService,
-               logger:         logger,
+               rmrSender:       rmrSender,
+               logger:          logger,
        }
 }
 
-func (handler *X2ResetRequestHandler) Handle(request models.Request) error {
+func (handler *X2ResetRequestHandler) Handle(request models.Request) (models.IResponse, error) {
+
        resetRequest := request.(models.ResetRequest)
+       handler.logger.Infof("#X2ResetRequestHandler.Handle - Ran name: %s", resetRequest.RanName)
 
        if len(resetRequest.Cause) == 0 {
                resetRequest.Cause = e2pdus.OmInterventionCause
        }
+
        payload, ok := e2pdus.KnownCausesToX2ResetPDU(resetRequest.Cause)
+
        if !ok {
-               handler.logger.Errorf("#reset_request_handler.Handle - Unknown cause (%s)", resetRequest.Cause)
-               return e2managererrors.NewRequestValidationError()
+               handler.logger.Errorf("#X2ResetRequestHandler.Handle - Unknown cause (%s)", resetRequest.Cause)
+               return nil, e2managererrors.NewRequestValidationError()
        }
 
        nodeb, err := handler.rNibDataService.GetNodeb(resetRequest.RanName)
        if err != nil {
-               handler.logger.Errorf("#reset_request_handler.Handle - failed to get status of RAN: %s from RNIB. Error: %s", resetRequest.RanName, err.Error())
+               handler.logger.Errorf("#X2ResetRequestHandler.Handle - failed to get status of RAN: %s from RNIB. Error: %s", resetRequest.RanName, err.Error())
                _, ok := err.(*common.ResourceNotFoundError)
                if ok {
-                       return e2managererrors.NewResourceNotFoundError()
+                       return nil, e2managererrors.NewResourceNotFoundError()
                }
-               return e2managererrors.NewRnibDbError()
+               return nil, e2managererrors.NewRnibDbError()
        }
 
        if nodeb.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
-               handler.logger.Errorf("#reset_request_handler.Handle - RAN: %s in wrong state (%s)", resetRequest.RanName, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
-               return e2managererrors.NewWrongStateError(X2_RESET_ACTIVITY_NAME, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
+               handler.logger.Errorf("#X2ResetRequestHandler.Handle - RAN: %s in wrong state (%s)", resetRequest.RanName, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
+               return nil, e2managererrors.NewWrongStateError(X2_RESET_ACTIVITY_NAME, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
        }
 
-       response := models.NotificationResponse{MgsType: rmrCgo.RIC_X2_RESET, RanName: resetRequest.RanName, Payload: payload}
-       if err := handler.rmrService.SendRmrMessage(&response); err != nil {
-               handler.logger.Errorf("#reset_request_handler.Handle - failed to send reset message to RMR: %s", err)
-               return e2managererrors.NewRmrError()
+       msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET, resetRequest.RanName, payload)
+
+       err = handler.rmrSender.Send(msg)
+
+       if err != nil {
+               handler.logger.Errorf("#X2ResetRequestHandler.Handle - failed to send reset message to RMR: %s", err)
+               return nil, e2managererrors.NewRmrError()
        }
 
-       handler.logger.Infof("#reset_request_handler.Handle - sent x2 reset to RAN: %s with cause: %s", resetRequest.RanName, resetRequest.Cause)
-       return nil
+       handler.logger.Infof("#X2ResetRequestHandler.Handle - sent x2 reset to RAN: %s with cause: %s", resetRequest.RanName, resetRequest.Cause)
+
+       return nil, nil
 }
index 64e0c10..870385b 100644 (file)
@@ -13,11 +13,10 @@ import (
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
-       "github.com/stretchr/testify/mock"
        "testing"
 )
 
-func setupX2ResetRequestHandlerTest(t *testing.T) (*X2ResetRequestHandler, *mocks.RmrMessengerMock, *mocks.RnibReaderMock){
+func setupX2ResetRequestHandlerTest(t *testing.T) (*X2ResetRequestHandler, *mocks.RmrMessengerMock, *mocks.RnibReaderMock) {
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
        readerMock := &mocks.RnibReaderMock{}
@@ -30,8 +29,8 @@ func setupX2ResetRequestHandlerTest(t *testing.T) (*X2ResetRequestHandler, *mock
        }
        rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
        rmrMessengerMock := &mocks.RmrMessengerMock{}
-       rmrService := getRmrService(rmrMessengerMock, log)
-       handler := NewX2ResetRequestHandler(log, rmrService, rnibDataService)
+       rmrSender := getRmrSender(rmrMessengerMock, log)
+       handler := NewX2ResetRequestHandler(log, rmrSender, rnibDataService)
 
        return handler, rmrMessengerMock, readerMock
 }
@@ -44,12 +43,12 @@ func TestHandleSuccessfulDefaultCause(t *testing.T) {
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", msg).Return(msg, nil)
 
        var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
        readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
 
-       actual := handler.Handle(models.ResetRequest{RanName: ranName})
+       _, actual := handler.Handle(models.ResetRequest{RanName: ranName})
 
        assert.Nil(t, actual)
 }
@@ -61,12 +60,12 @@ func TestHandleSuccessfulRequestedCause(t *testing.T) {
        payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", msg).Return(msg, nil)
 
        var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
        readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
 
-       actual := handler.Handle(models.ResetRequest{RanName: ranName, Cause: "protocol:transfer-syntax-error"})
+       _, actual := handler.Handle(models.ResetRequest{RanName: ranName, Cause: "protocol:transfer-syntax-error"})
 
        assert.Nil(t, actual)
 }
@@ -78,7 +77,7 @@ func TestHandleFailureUnknownCause(t *testing.T) {
        var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
        readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
 
-       actual := handler.Handle(models.ResetRequest{RanName: ranName, Cause: "XXX"})
+       _, actual := handler.Handle(models.ResetRequest{RanName: ranName, Cause: "XXX"})
 
        assert.IsType(t, e2managererrors.NewRequestValidationError(), actual)
 
@@ -91,7 +90,7 @@ func TestHandleFailureWrongState(t *testing.T) {
        var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
        readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
 
-       actual := handler.Handle(models.ResetRequest{RanName: ranName})
+       _, actual := handler.Handle(models.ResetRequest{RanName: ranName})
 
        assert.IsType(t, e2managererrors.NewWrongStateError(X2_RESET_ACTIVITY_NAME, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)]), actual)
 }
@@ -103,7 +102,7 @@ func TestHandleFailureRanNotFound(t *testing.T) {
 
        readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("nodeb not found"))
 
-       actual := handler.Handle(models.ResetRequest{RanName: ranName})
+       _, actual := handler.Handle(models.ResetRequest{RanName: ranName})
 
        assert.IsType(t, e2managererrors.NewResourceNotFoundError(), actual)
 }
@@ -115,7 +114,7 @@ func TestHandleFailureRnibError(t *testing.T) {
 
        readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{}, common.NewInternalError(fmt.Errorf("internal error")))
 
-       actual := handler.Handle(models.ResetRequest{RanName: ranName})
+       _, actual := handler.Handle(models.ResetRequest{RanName: ranName})
 
        assert.IsType(t, e2managererrors.NewRnibDbError(), actual)
 }
@@ -128,12 +127,12 @@ func TestHandleFailureRmrError(t *testing.T) {
        payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr error"))
+       rmrMessengerMock.On("SendMsg", msg).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr error"))
 
        var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
        readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
 
-       actual := handler.Handle(models.ResetRequest{RanName: ranName})
+       _, actual := handler.Handle(models.ResetRequest{RanName: ranName})
 
        assert.IsType(t, e2managererrors.NewRmrError(), actual)
 }
index 783f714..5de5e2d 100644 (file)
@@ -26,36 +26,38 @@ import (
 )
 
 type E2TermInitNotificationHandler struct {
+       logger                 *logger.Logger
        rnibDataService        services.RNibDataService
        ranReconnectionManager *managers.RanReconnectionManager
 }
 
-func NewE2TermInitNotificationHandler(ranReconnectionManager *managers.RanReconnectionManager, rnibDataService services.RNibDataService) E2TermInitNotificationHandler {
+func NewE2TermInitNotificationHandler(logger *logger.Logger, ranReconnectionManager *managers.RanReconnectionManager, rnibDataService services.RNibDataService) E2TermInitNotificationHandler {
        return E2TermInitNotificationHandler{
+               logger:                 logger,
                rnibDataService:        rnibDataService,
                ranReconnectionManager: ranReconnectionManager,
        }
 }
 
-func (handler E2TermInitNotificationHandler) Handle(logger *logger.Logger, request *models.NotificationRequest, messageChannel chan<- *models.NotificationResponse) {
+func (h E2TermInitNotificationHandler) Handle(request *models.NotificationRequest) {
 
-       logger.Infof("#E2TermInitNotificationHandler.Handle - Handling E2_TERM_INIT")
+       h.logger.Infof("#E2TermInitNotificationHandler.Handle - Handling E2_TERM_INIT")
 
-       nbIdentityList, err := handler.rnibDataService.GetListNodebIds()
+       nbIdentityList, err := h.rnibDataService.GetListNodebIds()
        if err != nil {
-               logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed to get nodes list from RNIB. Error: %s", err.Error())
+               h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed to get nodes list from RNIB. Error: %s", err.Error())
                return
        }
 
        if len(nbIdentityList) == 0 {
-               logger.Warnf("#E2TermInitNotificationHandler.Handle - The Nodes list in RNIB is empty")
+               h.logger.Warnf("#E2TermInitNotificationHandler.Handle - The Nodes list in RNIB is empty")
                return
        }
 
        for _, nbIdentity := range nbIdentityList {
 
-               if err := handler.ranReconnectionManager.ReconnectRan(nbIdentity.InventoryName); err != nil {
-                       logger.Errorf("#E2TermInitNotificationHandler.Handle - Ran name: %s - connection attempt failure, error: %s", (*nbIdentity).GetInventoryName(), err.Error())
+               if err := h.ranReconnectionManager.ReconnectRan(nbIdentity.InventoryName); err != nil {
+                       h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Ran name: %s - connection attempt failure, error: %s", (*nbIdentity).GetInventoryName(), err.Error())
                        _, ok := err.(*common.ResourceNotFoundError)
                        if !ok {
                                break
@@ -63,5 +65,5 @@ func (handler E2TermInitNotificationHandler) Handle(logger *logger.Logger, reque
                }
        }
 
-       logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT")
+       h.logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT")
 }
index 308d970..ae88cb2 100644 (file)
@@ -10,6 +10,7 @@ import (
        "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
@@ -25,7 +26,7 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotifica
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
        rmrMessengerMock := &mocks.RmrMessengerMock{}
-       rmrService := getRmrService(rmrMessengerMock, logger)
+       rmrSender := initRmrSender(rmrMessengerMock, logger)
 
        readerMock := &mocks.RnibReaderMock{}
        rnibReaderProvider := func() reader.RNibReader {
@@ -36,14 +37,14 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotifica
                return writerMock
        }
        rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
-       ranSetupManager := managers.NewRanSetupManager(logger, rmrService, rnibDataService)
+       ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
        ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
-       handler := NewE2TermInitNotificationHandler(ranReconnectionManager, rnibDataService)
+       handler := NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService)
        return logger, handler, readerMock, writerMock, rmrMessengerMock
 }
 
 func TestE2TerminInitHandlerSuccessOneRan(t *testing.T) {
-       log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
        var rnibErr error
 
        ids := []*entities.NbIdentity{{InventoryName: "test1"}}
@@ -59,16 +60,16 @@ func TestE2TerminInitHandlerSuccessOneRan(t *testing.T) {
        xaction := []byte(ids[0].InventoryName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
-       handler.Handle(log, nil, nil)
+       handler.Handle(nil)
 
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
 }
 
 func TestE2TerminInitHandlerSuccessTwoRans(t *testing.T) {
-       log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
        var rnibErr error
 
        ids := []*entities.NbIdentity{{InventoryName: "test1"}, {InventoryName: "test2"}}
@@ -86,9 +87,9 @@ func TestE2TerminInitHandlerSuccessTwoRans(t *testing.T) {
        xaction := []byte(ids[0].InventoryName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[0].InventoryName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
-       handler.Handle(log, nil, nil)
+       handler.Handle(nil)
 
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2)
@@ -122,9 +123,9 @@ func TestE2TerminInitHandlerSuccessThreeRansFirstRmrFailure(t *testing.T) {
        //xaction = []byte(ids[1].InventoryName)
        //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg0, fmt.Errorf("RMR Error"))
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, fmt.Errorf("RMR Error"))
 
-       handler.Handle(log, nil, nil)
+       handler.Handle(nil)
 
        //test1 (before send +1, after failure +1), test2 (0) test3 (0)
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
@@ -165,9 +166,9 @@ func TestE2TerminInitHandlerSuccessThreeRansSecondNotFoundFailure(t *testing.T)
        //xaction = []byte(ids[1].InventoryName)
        //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg0, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, nil)
 
-       handler.Handle(log, nil, nil)
+       handler.Handle(nil)
 
        readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
        //test1 (+1), test2 failure (0) test3 (+1)
@@ -209,9 +210,9 @@ func TestE2TerminInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *te
        //xaction = []byte(ids[1].InventoryName)
        //msg1 := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ids[1].InventoryName, &payload, &xaction)
 
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg0, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg0, nil)
 
-       handler.Handle(log, nil, nil)
+       handler.Handle(nil)
 
        readerMock.AssertNumberOfCalls(t, "GetNodeb", 2)
        //test1 (+1), test2 failure (0) test3 (0)
@@ -221,34 +222,33 @@ func TestE2TerminInitHandlerSuccessThreeRansSecondRnibInternalErrorFailure(t *te
 }
 
 func TestE2TerminInitHandlerSuccessZeroRans(t *testing.T) {
-       log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
        var rnibErr error
 
        readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, rnibErr)
 
-       handler.Handle(log, nil, nil)
+       handler.Handle(nil)
 
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
 }
 
 func TestE2TerminInitHandlerFailureGetListNodebIds(t *testing.T) {
-       log, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
+       _, handler, readerMock, writerMock, rmrMessengerMock := initRanLostConnectionTest(t)
 
        readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, common.NewInternalError(fmt.Errorf("internal error")))
 
-       handler.Handle(log, nil, nil)
+       handler.Handle(nil)
 
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
        rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
 }
 
 // TODO: extract to test_utils
-func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService {
+func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       messageChannel := make(chan *models.NotificationResponse)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, messageChannel)
+       return rmrsender.NewRmrSender(log, &rmrMessenger)
 }
 
 // TODO: extract to test_utils
index 88763a3..a6a6234 100644 (file)
@@ -12,12 +12,16 @@ import (
 )
 
 type EnbLoadInformationNotificationHandler struct {
+       logger          *logger.Logger
        rnibDataService services.RNibDataService
+       extractor       converters.IEnbLoadInformationExtractor
 }
 
-func NewEnbLoadInformationNotificationHandler(rnibDataService services.RNibDataService) EnbLoadInformationNotificationHandler {
+func NewEnbLoadInformationNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, extractor converters.IEnbLoadInformationExtractor) EnbLoadInformationNotificationHandler {
        return EnbLoadInformationNotificationHandler{
+               logger:          logger,
                rnibDataService: rnibDataService,
+               extractor: extractor,
        }
 }
 
@@ -25,34 +29,34 @@ func elapsed(startTime time.Time) float64 {
        return float64(time.Since(startTime)) / float64(time.Millisecond)
 }
 
-func (src EnbLoadInformationNotificationHandler) Handle(logger *logger.Logger, request *models.NotificationRequest, messageChannel chan<- *models.NotificationResponse) {
+func (h EnbLoadInformationNotificationHandler) Handle(request *models.NotificationRequest) {
 
-       pdu, err := converters.UnpackX2apPdu(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+       pdu, err := converters.UnpackX2apPdu(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
 
        if err != nil {
-               logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Unpack failed. Error: %v", request.RanName, err)
+               h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Unpack failed. Error: %v", request.RanName, err)
                return
        }
 
-       logger.Debugf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Unpacked message successfully", request.RanName)
+       h.logger.Debugf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Unpacked message successfully", request.RanName)
 
        ranLoadInformation := &entities.RanLoadInformation{LoadTimestamp: uint64(request.StartTime.UnixNano())}
 
-       err = converters.ExtractAndBuildRanLoadInformation(pdu, ranLoadInformation)
+       err = h.extractor.ExtractAndBuildRanLoadInformation(pdu, ranLoadInformation)
 
        if (err != nil) {
-               logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed at ExtractAndBuildRanLoadInformation. Error: %v", request.RanName, err)
+               h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed at ExtractAndBuildRanLoadInformation. Error: %v", request.RanName, err)
                return
        }
 
-       logger.Debugf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Successfully done with extracting and building RAN load information. elapsed: %f ms", request.RanName, elapsed(request.StartTime))
+       h.logger.Debugf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Successfully done with extracting and building RAN load information. elapsed: %f ms", request.RanName, elapsed(request.StartTime))
 
-       rnibErr := src.rnibDataService.SaveRanLoadInformation(request.RanName, ranLoadInformation)
+       rnibErr := h.rnibDataService.SaveRanLoadInformation(request.RanName, ranLoadInformation)
 
        if rnibErr != nil {
-               logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed saving RAN load information. Error: %v", request.RanName, rnibErr)
+               h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed saving RAN load information. Error: %v", request.RanName, rnibErr)
                return
        }
 
-       logger.Infof("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Successfully saved RAN load information to RNIB. elapsed: %f ms", request.RanName, elapsed(request.StartTime))
+       h.logger.Infof("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Successfully saved RAN load information to RNIB. elapsed: %f ms", request.RanName, elapsed(request.StartTime))
 }
index fb1fb4e..b11ed29 100644 (file)
@@ -18,7 +18,6 @@
 package rmrmsghandlers
 
 import (
-       "e2mgr/logger"
        "e2mgr/models"
        "fmt"
        "time"
@@ -26,7 +25,7 @@ import (
 
 const (
        FullUperPdu  string = "004c07080004001980da0100075bde017c148003d5a8205000017c180003d5a875555403331420000012883a0003547400cd20002801ea16007c1f07c1f107c1f0781e007c80800031a02c000c88199040a00352083669190000d8908020000be0c4001ead4016e007ab50100002f8320067ab5005b8c1ead5070190c00001d637805f220000f56a081400005f020000f56a1d555400ccc508002801ea16007c1f07c1f107c1f0781e007c80800031a02c000c88199040a00352083669190000d8908020000be044001ead4016e007ab50100002f8120067ab5005b8c1ead5070190c00000"
-       FullAperPdu string = "" // TODO: populate and use it
+       FullAperPdu  string = "" // TODO: populate and use it
        BasicUperPdu string = "004898000400190d0000074200017c148003d5a80000"
        BasicAperPdu string = "" // TODO: populate and use it
        GarbagePdu   string = "12312312"
@@ -44,14 +43,14 @@ func createNotificationRequest(ranName string, transactionId string, packedPdu s
        return models.NewNotificationRequest(ranName, packedByteSlice, time.Now(), transactionId), nil
 }
 
-func createNotificationRequestAndHandle(log *logger.Logger, ranName string, transactionId string, loadInformationHandler EnbLoadInformationNotificationHandler, pdu string) error {
+func createNotificationRequestAndHandle(ranName string, transactionId string, loadInformationHandler EnbLoadInformationNotificationHandler, pdu string) error {
        notificationRequest, err := createNotificationRequest(ranName, transactionId, pdu)
 
        if err != nil {
                return err
        }
 
-       loadInformationHandler.Handle(log, notificationRequest, nil)
+       loadInformationHandler.Handle(notificationRequest)
        return nil
 }
 
@@ -76,7 +75,7 @@ func createNotificationRequestAndHandle(log *logger.Logger, ranName string, tran
 //     var packedExampleByteSlice []byte
 //     _, err = fmt.Sscanf(FullUperPdu, "%x", &packedExampleByteSlice)
 //     notificationRequest := models.NewNotificationRequest(inventoryName, packedExampleByteSlice, time.Now(), " 881828026419")
-//     loadInformationHandler.Handle(log, notificationRequest, nil)
+//     loadInformationHandler.Handle(log, notificationRequest)
 //
 //     writerMock.AssertNumberOfCalls(t, "SaveRanLoadInformation", 1)
 //}
@@ -102,7 +101,7 @@ func createNotificationRequestAndHandle(log *logger.Logger, ranName string, tran
 //     var packedExampleByteSlice []byte
 //     _, err = fmt.Sscanf(GarbagePdu, "%x", &packedExampleByteSlice)
 //     notificationRequest := models.NewNotificationRequest(inventoryName, packedExampleByteSlice, time.Now(), " 881828026419")
-//     loadInformationHandler.Handle(log, notificationRequest, nil)
+//     loadInformationHandler.Handle(log, notificationRequest)
 //
 //     writerMock.AssertNumberOfCalls(t, "SaveRanLoadInformation", 0)
 //}
@@ -120,13 +119,13 @@ func createNotificationRequestAndHandle(log *logger.Logger, ranName string, tran
 //     defer reader.Close()
 //     loadInformationHandler := NewEnbLoadInformationNotificationHandler(rNibWriter.GetRNibWriter)
 //
-//     err = createNotificationRequestAndHandle(log, "ranName", " 881828026419", loadInformationHandler, FullUperPdu)
+//     err = createNotificationRequestAndHandle("ranName", " 881828026419", loadInformationHandler, FullUperPdu)
 //
 //     if err != nil {
 //             t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - failed creating NotificationRequest, error: %v", err)
 //     }
 //
-//     err = createNotificationRequestAndHandle(log, "ranName", " 881828026419", loadInformationHandler, BasicUperPdu)
+//     err = createNotificationRequestAndHandle("ranName", " 881828026419", loadInformationHandler, BasicUperPdu)
 //
 //     if err != nil {
 //             t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - failed creating NotificationRequest, error: %v", err)
index 2baa3f6..bcb2c44 100644 (file)
@@ -28,45 +28,53 @@ import (
        "e2mgr/logger"
        "e2mgr/models"
        "e2mgr/rmrCgo"
+       "e2mgr/services/rmrsender"
        "unsafe"
 )
 
-type EndcConfigurationUpdateHandler struct{}
+type EndcConfigurationUpdateHandler struct {
+       logger *logger.Logger
+       rmrSender *rmrsender.RmrSender
+}
 
-func NewEndcConfigurationUpdateHandler() EndcConfigurationUpdateHandler {
-       return EndcConfigurationUpdateHandler{}
+func NewEndcConfigurationUpdateHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender) EndcConfigurationUpdateHandler {
+       return EndcConfigurationUpdateHandler{
+               logger: logger,
+               rmrSender: rmrSender,
+       }
 }
 
-func (src EndcConfigurationUpdateHandler) Handle(logger *logger.Logger, request *models.NotificationRequest, messageChannel chan<- *models.NotificationResponse) {
+func (h EndcConfigurationUpdateHandler) Handle(request *models.NotificationRequest) {
 
        var payloadSize C.ulong
        payloadSize = e2pdus.MaxAsn1PackedBufferSize
        packedBuffer := [e2pdus.MaxAsn1PackedBufferSize]C.uchar{}
        errorBuffer := [e2pdus.MaxAsn1PackedBufferSize]C.char{}
-       refinedMessage, err := converters.UnpackX2apPduAndRefine(logger, e2pdus.MaxAsn1CodecAllocationBufferSize /*allocation buffer*/, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
+       refinedMessage, err := converters.UnpackX2apPduAndRefine(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize /*allocation buffer*/, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
        if err != nil {
                status := C.build_pack_endc_configuration_update_failure(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
                if status {
                        payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
-                       logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update negative ack message payload: (%d) %02x", len(payload), payload)
-                       response := models.NotificationResponse{RanName: request.RanName, Payload: payload, MgsType: rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE}
-                       messageChannel <- &response
+                       h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update negative ack message payload: (%d) %02x", len(payload), payload)
+                       msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, request.RanName, payload)
+                       _ = h.rmrSender.Send(msg)
                } else {
-                       logger.Errorf("#endc_configuration_update_handler.Handle - failed to build and pack Endc configuration update unsuccessful outcome message. Error: %v", errorBuffer)
+                       h.logger.Errorf("#endc_configuration_update_handler.Handle - failed to build and pack Endc configuration update unsuccessful outcome message. Error: %v", errorBuffer)
                }
-               logger.Errorf("#endc_configuration_update_handler.Handle - unpack failed. Error: %v", err)
+               h.logger.Errorf("#endc_configuration_update_handler.Handle - unpack failed. Error: %v", err)
        } else {
-               logger.Infof("#endc_configuration_update_handler.Handle - Endc configuration update initiating message received")
-               logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update initiating message payload: %s", refinedMessage.PduPrint)
+               h.logger.Infof("#endc_configuration_update_handler.Handle - Endc configuration update initiating message received")
+               h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update initiating message payload: %s", refinedMessage.PduPrint)
                status := C.build_pack_endc_configuration_update_ack(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
                if status {
                        payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
-                       logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update positive ack message payload: (%d) %02x", len(payload), payload)
-                       response := models.NotificationResponse{RanName: request.RanName, Payload: payload, MgsType: rmrCgo.RIC_ENDC_CONF_UPDATE_ACK}
-                       messageChannel <- &response
+                       h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update positive ack message payload: (%d) %02x", len(payload), payload)
+                       msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, request.RanName, payload)
+                       _ = h.rmrSender.Send(msg)
                } else {
-                       logger.Errorf("#endc_configuration_update_handler.Handle - failed to build and pack endc configuration update successful outcome message. Error: %v", errorBuffer)
+                       h.logger.Errorf("#endc_configuration_update_handler.Handle - failed to build and pack endc configuration update successful outcome message. Error: %v", errorBuffer)
                }
        }
-       printHandlingSetupResponseElapsedTimeInMs(logger, "#endc_configuration_update_handler.Handle - Summary: Elapsed time for receiving and handling endc configuration update initiating message from E2 terminator", request.StartTime)
+
+       printHandlingSetupResponseElapsedTimeInMs(h.logger, "#endc_configuration_update_handler.Handle - Summary: Elapsed time for receiving and handling endc configuration update initiating message from E2 terminator", request.StartTime)
 }
index 9005924..b7518a1 100644 (file)
 package rmrmsghandlers
 
 import (
-       "e2mgr/logger"
+       "e2mgr/mocks"
        "e2mgr/models"
        "e2mgr/rmrCgo"
-       "e2mgr/tests"
-       "github.com/stretchr/testify/assert"
+       "fmt"
        "testing"
        "time"
 )
 
-func TestHandleSuccessEndcConfigUpdate(t *testing.T) {
-       /*      log, err := logger.InitLogger(logger.InfoLevel)
-               if err!=nil{
-                       t.Errorf("#endc_configuration_update_handler_test.TestHandleSuccessEndcConfigUpdate - failed to initialize logger, error: %s", err)
-               }
-               h := EndcConfigurationUpdateHandler{}
+const PackedEndcConfigurationUpdateAck = "2025000a00000100f70003000000"
+const PackedEndcConfigurationUpdateFailure = "402500080000010005400142"
 
-               payload := tests.GetPackedPayload(t)
-               mBuf := rmrCgo.NewMBuf(10370, len(payload),"RanName", &payload, &tests.DummyXAction)
-               notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now()}
-               messageChannel := make(chan *models.NotificationResponse)
-
-               go h.Handle(log, &notificationRequest, messageChannel)
+func initEndcConfigurationUpdateHandlerTest(t *testing.T) (EndcConfigurationUpdateHandler, *mocks.RmrMessengerMock) {
+       log := initLog(t)
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, log)
+       h := NewEndcConfigurationUpdateHandler(log, rmrSender)
+       return h, rmrMessengerMock
+}
 
-               response := <-messageChannel
+func TestHandleEndcConfigUpdateSuccess(t *testing.T) {
+       h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
 
-               assert.NotEmpty(t, response)
-               assert.EqualValues(t, 10371, response.MgsType)
-               assert.True(t, len(response.Payload) > 0)*/
-}
+       ranName := "test"
+       xaction := []byte(ranName)
 
-func TestHandleFailureEndcConfigUpdate(t *testing.T) {
-       log, err := logger.InitLogger(logger.InfoLevel)
-       if err != nil {
-               t.Errorf("#endc_configuration_update_handler_test.TestHandleFailureEndcConfigUpdate - failed to initialize logger, error: %s", err)
-       }
-       h := EndcConfigurationUpdateHandler{}
+       var payload []byte
+       _, _ = fmt.Sscanf(PackedEndcConfigurationUpdateAck, "%x", &payload)
 
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, 4, "RanName", &tests.DummyPayload, &tests.DummyXAction)
+       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, len(payload), ranName, &payload, &xaction)
        notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now()}
-       messageChannel := make(chan *models.NotificationResponse)
+       var err error
+       rmrMessengerMock.On("SendMsg", mBuf).Return(&rmrCgo.MBuf{}, err)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+}
+
+func TestHandleEndcConfigUpdateFailure(t *testing.T) {
+       h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
 
-       go h.Handle(log, &notificationRequest, messageChannel)
+       ranName := "test"
+       xaction := []byte(ranName)
 
-       response := <-messageChannel
+       var payload []byte
+       _, _ = fmt.Sscanf(PackedEndcConfigurationUpdateFailure, "%x", &payload)
 
-       assert.NotEmpty(t, response)
-       assert.EqualValues(t, 10372, response.MgsType)
-       assert.True(t, len(response.Payload) > 0)
+       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, len(payload), ranName, &payload, &xaction)
+       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0}, StartTime: time.Now()}
+       rmrMessengerMock.On("SendMsg", mBuf).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
 }
index 51fa2d3..ec1b887 100644 (file)
@@ -24,10 +24,10 @@ import (
 )
 
 type NotificationHandler interface {
-       Handle(*logger.Logger, *models.NotificationRequest, chan<- *models.NotificationResponse)
+       Handle(*models.NotificationRequest)
 }
 
 //TODO: remove that
 func printHandlingSetupResponseElapsedTimeInMs(logger *logger.Logger, msg string, startTime time.Time) {
        logger.Infof("%s: %f ms", msg, float64(time.Since(startTime))/float64(time.Millisecond))
-}
\ No newline at end of file
+}
index e6ba81e..61b1393 100644 (file)
@@ -25,18 +25,20 @@ import (
 
 type RanLostConnectionHandler struct {
        ranReconnectionManager managers.IRanReconnectionManager
+       logger                 *logger.Logger
 }
 
-func NewRanLostConnectionHandler(ranReconnectionManager managers.IRanReconnectionManager) RanLostConnectionHandler {
+func NewRanLostConnectionHandler(logger *logger.Logger, ranReconnectionManager managers.IRanReconnectionManager) RanLostConnectionHandler {
        return RanLostConnectionHandler{
+               logger:                 logger,
                ranReconnectionManager: ranReconnectionManager,
        }
 }
-func (handler RanLostConnectionHandler) Handle(logger *logger.Logger, request *models.NotificationRequest, messageChannel chan<- *models.NotificationResponse) {
+func (h RanLostConnectionHandler) Handle(request *models.NotificationRequest) {
 
        ranName := request.RanName
 
-       logger.Warnf("#RanLostConnectionHandler.Handle - RAN name: %s - Received lost connection notification", ranName)
+       h.logger.Warnf("#RanLostConnectionHandler.Handle - RAN name: %s - Received lost connection notification", ranName)
 
-       _ = handler.ranReconnectionManager.ReconnectRan(ranName)
+       _ = h.ranReconnectionManager.ReconnectRan(ranName)
 }
index 176d901..babe4ab 100644 (file)
@@ -30,8 +30,8 @@ func TestLostConnectionHandlerSuccess(t *testing.T) {
        notificationRequest := models.NotificationRequest{RanName: ranName}
        ranReconnectionManagerMock := &mocks.RanReconnectionManagerMock{}
        ranReconnectionManagerMock.On("ReconnectRan", ranName).Return(nil)
-       handler := NewRanLostConnectionHandler(ranReconnectionManagerMock)
-       handler.Handle(logger, &notificationRequest, nil)
+       handler := NewRanLostConnectionHandler(logger, ranReconnectionManagerMock)
+       handler.Handle(&notificationRequest)
        ranReconnectionManagerMock.AssertCalled(t, "ReconnectRan", ranName)
 }
 
@@ -41,7 +41,7 @@ func TestLostConnectionHandlerFailure(t *testing.T) {
        notificationRequest := models.NotificationRequest{RanName: ranName}
        ranReconnectionManagerMock := &mocks.RanReconnectionManagerMock{}
        ranReconnectionManagerMock.On("ReconnectRan", ranName).Return(errors.New("error"))
-       handler := NewRanLostConnectionHandler(ranReconnectionManagerMock)
-       handler.Handle(logger, &notificationRequest, nil)
+       handler := NewRanLostConnectionHandler(logger, ranReconnectionManagerMock)
+       handler.Handle(&notificationRequest)
        ranReconnectionManagerMock.AssertCalled(t, "ReconnectRan", ranName)
-}
\ No newline at end of file
+}
index f6b63f3..30b1a37 100644 (file)
 package rmrmsghandlers
 
 import (
+       "e2mgr/enums"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/models"
+       "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/utils"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
 type SetupResponseNotificationHandler struct {
-       rnibDataService      services.RNibDataService
-       setupResponseManager managers.ISetupResponseManager
-       notificationType     string
+       logger                 *logger.Logger
+       rnibDataService        services.RNibDataService
+       setupResponseManager   managers.ISetupResponseManager
+       ranStatusChangeManager managers.IRanStatusChangeManager
+       msgType                int
 }
 
-func NewSetupResponseNotificationHandler(rnibDataService services.RNibDataService, setupResponseManager managers.ISetupResponseManager, notificationType string) SetupResponseNotificationHandler {
+var msgTypeToMsgName = map[int]string{
+       rmrCgo.RIC_X2_SETUP_RESP:         "X2 Setup Response",
+       rmrCgo.RIC_X2_SETUP_FAILURE:      "X2 Setup Failure Response",
+       rmrCgo.RIC_ENDC_X2_SETUP_RESP:    "ENDC Setup Response",
+       rmrCgo.RIC_ENDC_X2_SETUP_FAILURE: "ENDC Setup Failure Response",
+}
+
+func NewSetupResponseNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, setupResponseManager managers.ISetupResponseManager, ranStatusChangeManager managers.IRanStatusChangeManager, msgType int) SetupResponseNotificationHandler {
        return SetupResponseNotificationHandler{
-               rnibDataService:      rnibDataService,
-               setupResponseManager: setupResponseManager,
-               notificationType:     notificationType,
+               logger: logger,
+               rnibDataService:        rnibDataService,
+               setupResponseManager:   setupResponseManager,
+               ranStatusChangeManager: ranStatusChangeManager,
+               msgType:                msgType,
        }
 }
 
-func (h SetupResponseNotificationHandler) Handle(logger *logger.Logger, request *models.NotificationRequest, messageChannel chan<- *models.NotificationResponse) {
-       logger.Infof("#SetupResponseNotificationHandler - RAN name: %s - Received %s notification", request.RanName, h.notificationType)
+func (h SetupResponseNotificationHandler) Handle(request *models.NotificationRequest) {
+       msgName := msgTypeToMsgName[h.msgType]
+       h.logger.Infof("#SetupResponseNotificationHandler - RAN name: %s - Received %s notification", request.RanName, msgName)
 
        inventoryName := request.RanName
 
        nodebInfo, rnibErr := h.rnibDataService.GetNodeb(inventoryName)
 
        if rnibErr != nil {
-               logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Error fetching RAN from rNib: %v", request.RanName, rnibErr)
+               h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Error fetching RAN from rNib: %v", request.RanName, rnibErr)
                return
        }
 
        if !isConnectionStatusValid(nodebInfo.ConnectionStatus) {
-               logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Invalid RAN connection status: %s", request.RanName, nodebInfo.ConnectionStatus)
+               h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Invalid RAN connection status: %s", request.RanName, nodebInfo.ConnectionStatus)
                return
        }
 
        nodebInfo.ConnectionAttempts = 0
        nbIdentity := &entities.NbIdentity{InventoryName: inventoryName}
-       err := h.setupResponseManager.PopulateNodebByPdu(logger, nbIdentity, nodebInfo, request.Payload)
+       err := h.setupResponseManager.PopulateNodebByPdu(h.logger, nbIdentity, nodebInfo, request.Payload)
 
        if err != nil {
                return
@@ -66,13 +81,24 @@ func (h SetupResponseNotificationHandler) Handle(logger *logger.Logger, request
        rnibErr = h.rnibDataService.SaveNodeb(nbIdentity, nodebInfo)
 
        if rnibErr != nil {
-               logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Error saving RAN to rNib: %v", request.RanName, rnibErr)
+               h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Error saving RAN to rNib: %v", request.RanName, rnibErr)
+               return
+       }
+
+       h.logger.Infof("#SetupResponseNotificationHandler - RAN name: %s - Successfully saved RAN to rNib", request.RanName)
+       h.logger.Infof("#SetupResponseNotificationHandler - Summary: elapsed time for receiving and handling setup response message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
+
+       if !isSuccessSetupResponseMessage(h.msgType) {
                return
        }
 
-       logger.Infof("#SetupResponseNotificationHandler - RAN name: %s - Successfully saved RAN to rNib", request.RanName)
+       _ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_CONNECTED, enums.RIC_TO_RAN, nodebInfo)
 }
 
 func isConnectionStatusValid(connectionStatus entities.ConnectionStatus) bool {
        return connectionStatus == entities.ConnectionStatus_CONNECTING || connectionStatus == entities.ConnectionStatus_CONNECTED
 }
+
+func isSuccessSetupResponseMessage(msgType int) bool {
+       return msgType == rmrCgo.RIC_X2_SETUP_RESP || msgType == rmrCgo.RIC_ENDC_X2_SETUP_RESP
+}
index d4503b8..55f6012 100644 (file)
@@ -19,12 +19,18 @@ package rmrmsghandlers
 
 import (
        "e2mgr/configuration"
+       "e2mgr/converters"
+       "e2mgr/e2managererrors"
+       "e2mgr/enums"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/mocks"
        "e2mgr/models"
        "e2mgr/rNibWriter"
+       "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
+       "encoding/json"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -43,12 +49,31 @@ const (
        EndcSetupFailureResponsePackedPdu = "4024001a0000030005400200000016400100001140087821a00000008040"
 )
 
-type setupResponseTestContext struct {
-       logger               *logger.Logger
-       readerMock           *mocks.RnibReaderMock
-       writerMock           *mocks.RnibWriterMock
-       rnibDataService      services.RNibDataService
+type setupSuccessResponseTestCase struct {
+       packedPdu            string
+       setupResponseManager managers.ISetupResponseManager
+       msgType              int
+       saveNodebMockError   error
+       sendMsgError         error
+       statusChangeMbuf     *rmrCgo.MBuf
+}
+
+type setupFailureResponseTestCase struct {
+       packedPdu            string
        setupResponseManager managers.ISetupResponseManager
+       msgType              int
+       saveNodebMockError   error
+}
+
+type setupResponseTestContext struct {
+       logger                 *logger.Logger
+       readerMock             *mocks.RnibReaderMock
+       writerMock             *mocks.RnibWriterMock
+       rnibDataService        services.RNibDataService
+       setupResponseManager   managers.ISetupResponseManager
+       ranStatusChangeManager managers.IRanStatusChangeManager
+       rmrSender              *rmrsender.RmrSender
+       rmrMessengerMock       *mocks.RmrMessengerMock
 }
 
 func NewSetupResponseTestContext(manager managers.ISetupResponseManager) *setupResponseTestContext {
@@ -64,48 +89,58 @@ func NewSetupResponseTestContext(manager managers.ISetupResponseManager) *setupR
        }
        rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
 
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, logger)
+
+       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
+
        return &setupResponseTestContext{
-               logger:               logger,
-               readerMock:           readerMock,
-               writerMock:           writerMock,
-               rnibDataService:      rnibDataService,
-               setupResponseManager: manager,
+               logger:                 logger,
+               readerMock:             readerMock,
+               writerMock:             writerMock,
+               rnibDataService:        rnibDataService,
+               setupResponseManager:   manager,
+               ranStatusChangeManager: ranStatusChangeManager,
+               rmrMessengerMock:       rmrMessengerMock,
+               rmrSender:              rmrSender,
        }
 }
 
 func TestSetupResponseGetNodebFailure(t *testing.T) {
        notificationRequest := models.NotificationRequest{RanName: RanName}
        testContext := NewSetupResponseTestContext(nil)
-       handler := NewSetupResponseNotificationHandler(testContext.rnibDataService, &managers.X2SetupResponseManager{}, "X2 Setup Response")
+       handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, &managers.X2SetupResponseManager{}, testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
        testContext.readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewInternalError(errors.New("Error")))
-       handler.Handle(testContext.logger, &notificationRequest, nil)
+       handler.Handle(&notificationRequest)
        testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
        testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
+       testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
 func TestSetupResponseInvalidConnectionStatus(t *testing.T) {
        ranName := "test"
        notificationRequest := models.NotificationRequest{RanName: ranName}
        testContext := NewSetupResponseTestContext(nil)
-       handler := NewSetupResponseNotificationHandler(testContext.rnibDataService, &managers.X2SetupResponseManager{}, "X2 Setup Response")
+       handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, &managers.X2SetupResponseManager{}, testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
        var rnibErr error
        testContext.readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}, rnibErr)
-       handler.Handle(testContext.logger, &notificationRequest, nil)
+       handler.Handle(&notificationRequest)
        testContext.readerMock.AssertCalled(t, "GetNodeb", ranName)
        testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
+       testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
-func executeHandleSuccessSetupResponse(t *testing.T, packedPdu string, setupResponseManager managers.ISetupResponseManager, notificationType string, saveNodebMockReturnValue error) (*setupResponseTestContext, *entities.NodebInfo) {
+func executeHandleSetupSuccessResponse(t *testing.T, tc setupSuccessResponseTestCase) (*setupResponseTestContext, *entities.NodebInfo) {
        var payload []byte
-       _, err := fmt.Sscanf(packedPdu, "%x", &payload)
+       _, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
        if err != nil {
                t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
        }
 
        notificationRequest := models.NotificationRequest{RanName: RanName, Payload: payload}
-       testContext := NewSetupResponseTestContext(setupResponseManager)
+       testContext := NewSetupResponseTestContext(tc.setupResponseManager)
 
-       handler := NewSetupResponseNotificationHandler(testContext.rnibDataService, testContext.setupResponseManager, notificationType)
+       handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, testContext.setupResponseManager, testContext.ranStatusChangeManager, tc.msgType)
 
        var rnibErr error
 
@@ -118,15 +153,63 @@ func executeHandleSuccessSetupResponse(t *testing.T, packedPdu string, setupResp
        }
 
        testContext.readerMock.On("GetNodeb", RanName).Return(nodebInfo, rnibErr)
-       testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(saveNodebMockReturnValue)
-       handler.Handle(testContext.logger, &notificationRequest, nil)
+       testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(tc.saveNodebMockError)
+       testContext.rmrMessengerMock.On("SendMsg", tc.statusChangeMbuf).Return(&rmrCgo.MBuf{}, tc.sendMsgError)
+       handler.Handle(&notificationRequest)
 
        return testContext, nodebInfo
 }
 
-func TestX2SetupResponse(t *testing.T) {
+func getRanConnectedMbuf(nodeType entities.Node_Type) *rmrCgo.MBuf {
+       xaction := []byte(RanName)
+       resourceStatusPayload := models.NewResourceStatusPayload(nodeType, enums.RIC_TO_RAN)
+       resourceStatusJson, _ := json.Marshal(resourceStatusPayload)
+       return rmrCgo.NewMBuf(rmrCgo.RAN_CONNECTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xaction)
+}
+
+func executeHandleSetupFailureResponse(t *testing.T, tc setupFailureResponseTestCase) (*setupResponseTestContext, *entities.NodebInfo) {
+       var payload []byte
+       _, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
+       if err != nil {
+               t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
+       }
+
+       notificationRequest := models.NotificationRequest{RanName: RanName, Payload: payload}
+       testContext := NewSetupResponseTestContext(tc.setupResponseManager)
+
+       handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, testContext.setupResponseManager, testContext.ranStatusChangeManager, tc.msgType)
+
        var rnibErr error
-       testContext, nodebInfo := executeHandleSuccessSetupResponse(t, X2SetupResponsePackedPdu, &managers.X2SetupResponseManager{}, "X2 Setup Response", rnibErr)
+
+       nodebInfo := &entities.NodebInfo{
+               ConnectionStatus:   entities.ConnectionStatus_CONNECTING,
+               ConnectionAttempts: 1,
+               RanName:            RanName,
+               Ip:                 "10.0.2.2",
+               Port:               1231,
+       }
+
+       testContext.readerMock.On("GetNodeb", RanName).Return(nodebInfo, rnibErr)
+       testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(tc.saveNodebMockError)
+       handler.Handle(&notificationRequest)
+
+       return testContext, nodebInfo
+}
+
+func TestX2SetupResponse(t *testing.T) {
+       logger := initLog(t)
+       var saveNodebMockError error
+       var sendMsgError error
+       tc := setupSuccessResponseTestCase{
+               X2SetupResponsePackedPdu,
+               managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
+               rmrCgo.RIC_X2_SETUP_RESP,
+               saveNodebMockError,
+               sendMsgError,
+               getRanConnectedMbuf(entities.Node_ENB),
+       }
+
+       testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
        testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
        testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
        assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
@@ -136,22 +219,42 @@ func TestX2SetupResponse(t *testing.T) {
        assert.IsType(t, &entities.NodebInfo_Enb{}, nodebInfo.Configuration)
        i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
        assert.NotNil(t, i.Enb)
+       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf)
 }
 
 func TestX2SetupFailureResponse(t *testing.T) {
-       var rnibErr error
-       testContext, nodebInfo := executeHandleSuccessSetupResponse(t, X2SetupFailureResponsePackedPdu, &managers.X2SetupFailureResponseManager{}, "X2 Setup Failure Response", rnibErr)
+       logger := initLog(t)
+       var saveNodebMockError error
+       tc := setupFailureResponseTestCase{
+               X2SetupFailureResponsePackedPdu,
+               managers.NewX2SetupFailureResponseManager(converters.NewX2SetupFailureResponseConverter(logger)),
+               rmrCgo.RIC_X2_SETUP_FAILURE,
+               saveNodebMockError,
+       }
+
+       testContext, nodebInfo := executeHandleSetupFailureResponse(t, tc)
        testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
        testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
        assert.EqualValues(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
        assert.EqualValues(t, 0, nodebInfo.ConnectionAttempts)
        assert.EqualValues(t, entities.Failure_X2_SETUP_FAILURE, nodebInfo.FailureType)
        assert.NotNil(t, nodebInfo.SetupFailure)
+       testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
 func TestEndcSetupResponse(t *testing.T) {
-       var rnibErr error
-       testContext, nodebInfo := executeHandleSuccessSetupResponse(t, EndcSetupResponsePackedPdu, &managers.EndcSetupResponseManager{}, "ENDC Setup Response", rnibErr)
+       var saveNodebMockError error
+       var sendMsgError error
+       tc := setupSuccessResponseTestCase{
+               EndcSetupResponsePackedPdu,
+               &managers.EndcSetupResponseManager{},
+               rmrCgo.RIC_ENDC_X2_SETUP_RESP,
+               saveNodebMockError,
+               sendMsgError,
+               getRanConnectedMbuf(entities.Node_GNB),
+       }
+
+       testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
        testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
        testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
        assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
@@ -161,33 +264,84 @@ func TestEndcSetupResponse(t *testing.T) {
 
        i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Gnb)
        assert.NotNil(t, i.Gnb)
+       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf)
 }
+
 func TestEndcSetupFailureResponse(t *testing.T) {
-       var rnibErr error
-       testContext, nodebInfo := executeHandleSuccessSetupResponse(t, EndcSetupFailureResponsePackedPdu, &managers.EndcSetupFailureResponseManager{}, "ENDC Setup Failure Response", rnibErr)
+
+       var saveNodebMockError error
+       tc := setupFailureResponseTestCase{
+               EndcSetupFailureResponsePackedPdu,
+               &managers.EndcSetupFailureResponseManager{},
+               rmrCgo.RIC_ENDC_X2_SETUP_FAILURE,
+               saveNodebMockError,
+       }
+
+       testContext, nodebInfo := executeHandleSetupFailureResponse(t, tc)
        testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
        testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
        assert.EqualValues(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
        assert.EqualValues(t, 0, nodebInfo.ConnectionAttempts)
        assert.EqualValues(t, entities.Failure_ENDC_X2_SETUP_FAILURE, nodebInfo.FailureType)
        assert.NotNil(t, nodebInfo.SetupFailure)
+       testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
 func TestSetupResponseInvalidPayload(t *testing.T) {
+       logger := initLog(t)
        ranName := "test"
        notificationRequest := models.NotificationRequest{RanName: ranName, Payload: []byte("123")}
        testContext := NewSetupResponseTestContext(nil)
-       handler := NewSetupResponseNotificationHandler(testContext.rnibDataService, &managers.X2SetupResponseManager{}, "X2 Setup Response")
+       handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)), testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
        var rnibErr error
        testContext.readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, ConnectionAttempts: 1}, rnibErr)
-       handler.Handle(testContext.logger, &notificationRequest, nil)
+       handler.Handle(&notificationRequest)
        testContext.readerMock.AssertCalled(t, "GetNodeb", ranName)
        testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
+       testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
 func TestSetupResponseSaveNodebFailure(t *testing.T) {
-       rnibErr := common.NewInternalError(errors.New("Error"))
-       testContext, nodebInfo := executeHandleSuccessSetupResponse(t, X2SetupResponsePackedPdu, &managers.X2SetupResponseManager{}, "X2 Setup Response", rnibErr)
+       logger := initLog(t)
+       saveNodebMockError := common.NewInternalError(errors.New("Error"))
+       var sendMsgError error
+       tc := setupSuccessResponseTestCase{
+               X2SetupResponsePackedPdu,
+               managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
+               rmrCgo.RIC_X2_SETUP_RESP,
+               saveNodebMockError,
+               sendMsgError,
+               getRanConnectedMbuf(entities.Node_ENB),
+       }
+
+       testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
+       testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
+       testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
+       testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
+
+func TestSetupResponseStatusChangeSendFailure(t *testing.T) {
+       logger := initLog(t)
+       var saveNodebMockError error
+       sendMsgError := e2managererrors.NewRmrError()
+       tc := setupSuccessResponseTestCase{
+               X2SetupResponsePackedPdu,
+               managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
+               rmrCgo.RIC_X2_SETUP_RESP,
+               saveNodebMockError,
+               sendMsgError,
+               getRanConnectedMbuf(entities.Node_ENB),
+       }
+
+       testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
        testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
        testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
+       assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
+       assert.EqualValues(t, 0, nodebInfo.ConnectionAttempts)
+       assert.EqualValues(t, entities.Node_ENB, nodebInfo.NodeType)
+
+       assert.IsType(t, &entities.NodebInfo_Enb{}, nodebInfo.Configuration)
+       i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
+       assert.NotNil(t, i.Enb)
+       testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf)
 }
index 622a338..0c5848f 100644 (file)
@@ -24,68 +24,81 @@ package rmrmsghandlers
 import "C"
 import (
        "e2mgr/e2pdus"
+       "e2mgr/enums"
        "e2mgr/logger"
+       "e2mgr/managers"
        "e2mgr/models"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
+       "e2mgr/utils"
+       "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "unsafe"
 )
 
 type X2ResetRequestNotificationHandler struct {
-       rnibDataService services.RNibDataService
+       logger                 *logger.Logger
+       rnibDataService        services.RNibDataService
+       ranStatusChangeManager managers.IRanStatusChangeManager
+       rmrSender              *rmrsender.RmrSender
 }
 
-func NewX2ResetRequestNotificationHandler(rnibDataService services.RNibDataService) X2ResetRequestNotificationHandler {
+func NewX2ResetRequestNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, ranStatusChangeManager managers.IRanStatusChangeManager, rmrSender *rmrsender.RmrSender) X2ResetRequestNotificationHandler {
        return X2ResetRequestNotificationHandler{
-               rnibDataService: rnibDataService,
+               logger:                 logger,
+               rnibDataService:        rnibDataService,
+               ranStatusChangeManager: ranStatusChangeManager,
+               rmrSender:              rmrSender,
        }
 }
 
-func (src X2ResetRequestNotificationHandler) Handle(logger *logger.Logger, request *models.NotificationRequest, messageChannel chan<- *models.NotificationResponse) {
+func (h X2ResetRequestNotificationHandler) Handle(request *models.NotificationRequest) {
 
-       logger.Debugf("#X2ResetRequestNotificationHandler.Handle - Ran name: %s", request.RanName)
+       h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Ran name: %s", request.RanName)
 
-       nb, rNibErr := src.rnibDataService.GetNodeb(request.RanName)
+       nb, rNibErr := h.rnibDataService.GetNodeb(request.RanName)
        if rNibErr != nil {
-               logger.Errorf("#X2ResetRequestNotificationHandler.Handle - failed to retrieve nodeB entity. RanName: %s. Error: %s", request.RanName, rNibErr.Error())
-               printHandlingSetupResponseElapsedTimeInMs(logger, "#X2ResetRequestNotificationHandler.Handle - Summary: Elapsed time for receiving and handling reset request message from E2 terminator", request.StartTime)
-
+               h.logger.Errorf("#X2ResetRequestNotificationHandler.Handle - failed to retrieve nodeB entity. RanName: %s. Error: %s", request.RanName, rNibErr.Error())
+               h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
                return
        }
-       logger.Debugf("#X2ResetRequestNotificationHandler.Handle - nodeB entity retrieved. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
 
-       if nb.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
-               logger.Warnf("#X2ResetRequestNotificationHandler.Handle - nodeB entity in incorrect state. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
-               printHandlingSetupResponseElapsedTimeInMs(logger, "#X2ResetRequestNotificationHandler.Handle - Summary: Elapsed time for receiving and handling reset request message from E2 terminator", request.StartTime)
+       h.logger.Debugf("#X2ResetRequestNotificationHandler.Handle - nodeB entity retrieved. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
 
+       if nb.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
+               h.logger.Warnf("#X2ResetRequestNotificationHandler.Handle - nodeB entity in incorrect state. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
+               h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
                return
        }
 
        if nb.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
-               logger.Errorf("#X2ResetRequestNotificationHandler.Handle - nodeB entity in incorrect state. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
-               printHandlingSetupResponseElapsedTimeInMs(logger, "#X2ResetRequestNotificationHandler.Handle - Summary: Elapsed time for receiving and handling reset request message from E2 terminator", request.StartTime)
+               h.logger.Errorf("#X2ResetRequestNotificationHandler.Handle - nodeB entity in incorrect state. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
+               h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
+               return
+       }
 
+       msg, err := createX2ResetResponseNotification(request)
+       if err != nil {
+               h.logger.Errorf("#X2ResetRequestNotificationHandler.Handle - %s", err)
                return
        }
-       src.createAndAddToChannel(logger, request, messageChannel)
 
-       //TODO change name of printHandlingSetupResponseElapsedTimeInMs (remove setup response) and move to utils?
-       printHandlingSetupResponseElapsedTimeInMs(logger, "#X2ResetRequestNotificationHandler.Handle - Summary: Elapsed time for receiving and handling reset request message from E2 terminator", request.StartTime)
+       _ = h.rmrSender.Send(msg)
+       h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
+       _ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_RESTARTED, enums.RAN_TO_RIC, nb)
 }
 
-func (src X2ResetRequestNotificationHandler) createAndAddToChannel(logger *logger.Logger, request *models.NotificationRequest, messageChannel chan<- *models.NotificationResponse) {
+func createX2ResetResponseNotification(request *models.NotificationRequest) (*models.RmrMessage, error) {
 
        packedBuffer := make([]C.uchar, e2pdus.MaxAsn1PackedBufferSize)
        errorBuffer := make([]C.char, e2pdus.MaxAsn1CodecMessageBufferSize)
        var payloadSize = C.ulong(e2pdus.MaxAsn1PackedBufferSize)
 
        if status := C.build_pack_x2reset_response(&payloadSize, &packedBuffer[0], C.ulong(e2pdus.MaxAsn1CodecMessageBufferSize), &errorBuffer[0]); !status {
-               logger.Errorf("#X2ResetRequestNotificationHandler.createAndAddToChannel - failed to build and pack the reset response message %s ", C.GoString(&errorBuffer[0]))
-               return
+               return nil, fmt.Errorf("failed to build and pack the reset response message %s ", C.GoString(&errorBuffer[0]))
        }
        payload := C.GoBytes(unsafe.Pointer(&packedBuffer[0]), C.int(payloadSize))
-       response := models.NotificationResponse{RanName: request.RanName, Payload: payload, MgsType: rmrCgo.RIC_X2_RESET_RESP}
-
-       messageChannel <- &response
+       msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET_RESP, request.RanName, payload)
+       return msg, nil
 }
index 309a57e..95b0306 100644 (file)
@@ -19,21 +19,23 @@ package rmrmsghandlers
 
 import (
        "e2mgr/configuration"
-       "e2mgr/logger"
+       "e2mgr/e2pdus"
+       "e2mgr/enums"
+       "e2mgr/managers"
        "e2mgr/mocks"
        "e2mgr/models"
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/tests"
+       "encoding/json"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
-       "github.com/stretchr/testify/assert"
        "testing"
        "time"
 )
 
-func initX2ResetRequestNotifHandlerTest(t *testing.T) (*logger.Logger, X2ResetRequestNotificationHandler, *mocks.RnibReaderMock) {
+func initX2ResetRequestNotificationHandlerTest(t *testing.T) (X2ResetRequestNotificationHandler, *mocks.RnibReaderMock, *mocks.RmrMessengerMock) {
        log := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
        readerMock := &mocks.RnibReaderMock{}
@@ -42,35 +44,40 @@ func initX2ResetRequestNotifHandlerTest(t *testing.T) (*logger.Logger, X2ResetRe
        }
        rnibDataService := services.NewRnibDataService(log, config, readerProvider, nil)
 
-       h := NewX2ResetRequestNotificationHandler(rnibDataService)
-       return log, h, readerMock
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, log)
+       ranStatusChangeManager := managers.NewRanStatusChangeManager(log, rmrSender)
+       h := NewX2ResetRequestNotificationHandler(log, rnibDataService, ranStatusChangeManager, rmrSender)
+       return h, readerMock, rmrMessengerMock
 }
 
-func TestX2ResetRequestNotifSuccess(t *testing.T) {
-       log, h, readerMock := initX2ResetRequestNotifHandlerTest(t)
-
-       payload := []byte("payload")
-
-       xaction := []byte("RanName")
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
-               StartTime: time.Now(), TransactionId: string(xaction)}
-
-       nb := &entities.NodebInfo{RanName: mBuf.Meid, ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
-       var rnibErr error
-       readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
-
-       messageChannel := make(chan *models.NotificationResponse)
-
-       go h.Handle(log, &notificationRequest, messageChannel)
+func getRanRestartedMbuf(nodeType entities.Node_Type, messageDirection enums.MessageDirection) *rmrCgo.MBuf {
+       xaction := []byte(RanName)
+       resourceStatusPayload := models.NewResourceStatusPayload(nodeType, messageDirection)
+       resourceStatusJson, _ := json.Marshal(resourceStatusPayload)
+       return rmrCgo.NewMBuf(rmrCgo.RAN_RESTARTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xaction)
+}
 
-       result := <-messageChannel
-       assert.Equal(t, result.RanName, mBuf.Meid)
-       assert.Equal(t, result.MgsType, rmrCgo.RIC_X2_RESET_RESP)
+func TestHandleX2ResetRequestNotificationSuccess(t *testing.T) {
+       h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
+       ranName := "test"
+       xaction := []byte(ranName)
+       notificationRequest := models.NewNotificationRequest(ranName, []byte{}, time.Now(), ranName)
+
+       nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
+       var err error
+       readerMock.On("GetNodeb", ranName).Return(nb, err)
+       resetResponseMbuf := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET_RESP, len(e2pdus.PackedX2ResetResponse), ranName, &e2pdus.PackedX2ResetResponse, &xaction)
+       rmrMessengerMock.On("SendMsg", resetResponseMbuf).Return(&rmrCgo.MBuf{}, err)
+       ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RAN_TO_RIC)
+       rmrMessengerMock.On("SendMsg", ranRestartedMbuf).Return(&rmrCgo.MBuf{}, err)
+       h.Handle(notificationRequest)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", resetResponseMbuf)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf)
 }
 
-func TestHandleX2ResetRequestNotifShuttingDownStatus(t *testing.T) {
-       log, h, readerMock := initX2ResetRequestNotifHandlerTest(t)
+func TestHandleX2ResetRequestNotificationShuttingDownStatus(t *testing.T) {
+       h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
        var payload []byte
 
        xaction := []byte("RanName")
@@ -83,29 +90,27 @@ func TestHandleX2ResetRequestNotifShuttingDownStatus(t *testing.T) {
 
        readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
 
-       h.Handle(log, &notificationRequest, nil)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
-func TestHandleX2ResetRequestNotifDisconnectStatus(t *testing.T) {
-       log, h, readerMock := initX2ResetRequestNotifHandlerTest(t)
+func TestHandleX2ResetRequestNotificationDisconnectStatus(t *testing.T) {
+       h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
        var payload []byte
-
        xaction := []byte("RanName")
        mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
-               StartTime: time.Now(), TransactionId: string(xaction)}
-
+       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now(), TransactionId: string(xaction)}
        nb := &entities.NodebInfo{RanName: mBuf.Meid, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
        var rnibErr error
-
        readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
 
-       h.Handle(log, &notificationRequest, nil)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
-func TestHandleX2ResetRequestNotifGetNodebFailed(t *testing.T) {
+func TestHandleX2ResetRequestNotificationGetNodebFailed(t *testing.T) {
 
-       log, h, readerMock := initX2ResetRequestNotifHandlerTest(t)
+        h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
        var payload []byte
        xaction := []byte("RanName")
        mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xaction)
@@ -116,5 +121,6 @@ func TestHandleX2ResetRequestNotifGetNodebFailed(t *testing.T) {
        rnibErr := &common.ResourceNotFoundError{}
        readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
 
-       h.Handle(log, &notificationRequest, nil)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
index 1ad7d98..3d6bd23 100644 (file)
@@ -23,35 +23,79 @@ package rmrmsghandlers
 import "C"
 import (
        "e2mgr/converters"
-       "e2mgr/e2pdus"
+       "e2mgr/enums"
        "e2mgr/logger"
+       "e2mgr/managers"
        "e2mgr/models"
+       "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/utils"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
 type X2ResetResponseHandler struct {
-       rnibDataService services.RNibDataService
+       logger                 *logger.Logger
+       rnibDataService        services.RNibDataService
+       ranStatusChangeManager managers.IRanStatusChangeManager
+       extractor              converters.IX2ResetResponseExtractor
 }
 
-func NewX2ResetResponseHandler(rnibDataService services.RNibDataService) X2ResetResponseHandler {
+func NewX2ResetResponseHandler(logger *logger.Logger, rnibDataService services.RNibDataService, ranStatusChangeManager managers.IRanStatusChangeManager, x2ResetResponseExtractor converters.IX2ResetResponseExtractor) X2ResetResponseHandler {
        return X2ResetResponseHandler{
-               rnibDataService: rnibDataService,
+               logger:                 logger,
+               rnibDataService:        rnibDataService,
+               ranStatusChangeManager: ranStatusChangeManager,
+               extractor:              x2ResetResponseExtractor,
        }
 }
 
-func (src X2ResetResponseHandler) Handle(logger *logger.Logger, request *models.NotificationRequest, messageChannel chan<- *models.NotificationResponse) {
+func (h X2ResetResponseHandler) Handle(request *models.NotificationRequest) {
+       ranName := request.RanName
+       h.logger.Infof("#X2ResetResponseHandler.Handle - RAN name: %s - received reset response. Payload: %x", ranName, request.Payload)
 
-       logger.Infof("#x2ResetResponseHandler.Handle - received reset response. Payload: %x", request.Payload)
+       nodebInfo, err := h.rnibDataService.GetNodeb(ranName);
+       if err != nil {
+               h.logger.Errorf("#x2ResetResponseHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
+               return
+       }
+
+       if nodebInfo.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
+               h.logger.Warnf("#X2ResetResponseHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", nodebInfo.RanName, nodebInfo.ConnectionStatus)
+               h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
+               return
+       }
+
+       if nodebInfo.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
+               h.logger.Errorf("#X2ResetResponseHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", nodebInfo.RanName, nodebInfo.ConnectionStatus)
+               h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
+               return
+       }
+
+       isSuccessfulResetResponse, err := h.isSuccessfulResetResponse(ranName, request.Payload)
+
+       h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
+
+       if err != nil || !isSuccessfulResetResponse {
+               return
+       }
+
+       _ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_RESTARTED, enums.RIC_TO_RAN, nodebInfo)
+}
+
+func (h X2ResetResponseHandler) isSuccessfulResetResponse(ranName string, packedBuffer []byte) (bool, error) {
 
-       if nb, rNibErr := src.rnibDataService.GetNodeb(request.RanName); rNibErr != nil {
-               logger.Errorf("#x2ResetResponseHandler.Handle - failed to retrieve nb entity. RanName: %s. Error: %s", request.RanName, rNibErr.Error())
-       } else {
-               logger.Debugf("#x2ResetResponseHandler.Handle - nb entity retrieved. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
-               refinedMessage, err := converters.UnpackX2apPduAndRefine(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
-               if err != nil {
-                       logger.Errorf("#x2ResetResponseHandler.Handle - failed to unpack reset response message. RanName %s, Payload: %s", request.RanName, request.Payload)
-               } else {
-                       logger.Debugf("#x2ResetResponseHandler.Handle - reset response message payload unpacked. RanName %s, Message: %s", request.RanName, refinedMessage.PduPrint)
-               }
+       criticalityDiagnostics, err := h.extractor.ExtractCriticalityDiagnosticsFromPdu(packedBuffer)
+
+       if err != nil {
+               h.logger.Errorf("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Failed extracting pdu: %s", ranName, err)
+               return false, err
+       }
+
+       if criticalityDiagnostics != nil {
+               h.logger.Errorf("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Unsuccessful RESET response message. Criticality diagnostics: %s", ranName, criticalityDiagnostics)
+               return false, nil
        }
+
+       h.logger.Infof("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Successful RESET response message", ranName)
+       return true, nil
 }
index 26f0ade..c051eeb 100644 (file)
@@ -19,12 +19,15 @@ package rmrmsghandlers
 
 import (
        "e2mgr/configuration"
+       "e2mgr/converters"
+       "e2mgr/enums"
        "e2mgr/logger"
+       "e2mgr/managers"
        "e2mgr/mocks"
        "e2mgr/models"
        "e2mgr/rmrCgo"
        "e2mgr/services"
-       "e2mgr/tests"
+       "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
@@ -32,79 +35,152 @@ import (
        "time"
 )
 
-func initX2ResetResponseHandlerTest(t *testing.T) (*logger.Logger, X2ResetResponseHandler, *mocks.RnibReaderMock) {
-       log, err := logger.InitLogger(logger.DebugLevel)
+const (
+       SuccessfulX2ResetResponsePackedPdu = "200700080000010011400100"
+       SuccessfulX2ResetResponsePackedPduEmptyIEs = "20070003000000"
+       UnsuccessfulX2ResetResponsePackedPdu = "2007000d00000100114006080000000d00"
+)
+
+func initX2ResetResponseHandlerTest(t *testing.T) (X2ResetResponseHandler, *mocks.RnibReaderMock, *mocks.RmrMessengerMock) {
+       log, err := logger.InitLogger(logger.InfoLevel)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
-       if err!=nil{
-               t.Errorf("#sctp_errors_notification_handler_test.TestHandleInSession - failed to initialize logger, error: %s", err)
+       if err != nil {
+               t.Errorf("#initX2ResetResponseHandlerTest - failed to initialize logger, error: %s", err)
        }
-       readerMock :=&mocks.RnibReaderMock{}
+       readerMock := &mocks.RnibReaderMock{}
        rnibReaderProvider := func() reader.RNibReader {
                return readerMock
        }
+
        rnibDataService := services.NewRnibDataService(log, config, rnibReaderProvider, nil)
 
-       h := NewX2ResetResponseHandler(rnibDataService)
-       return log, h, readerMock
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, log)
+       ranStatusChangeManager := managers.NewRanStatusChangeManager(log, rmrSender)
+
+       h := NewX2ResetResponseHandler(log, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(log))
+       return h, readerMock, rmrMessengerMock
 }
 
 func TestX2ResetResponseSuccess(t *testing.T) {
-       log, h, readerMock := initX2ResetResponseHandlerTest(t)
+       h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
+       var payload []byte
+       _, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
+       if err != nil {
+               t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
+       }
+
+       xaction := []byte(RanName)
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
+       var rnibErr error
+       readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
+       ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RIC_TO_RAN)
+       rmrMessengerMock.On("SendMsg", ranRestartedMbuf).Return(&rmrCgo.MBuf{}, err)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf)
+}
+
+func TestX2ResetResponseSuccessEmptyIEs(t *testing.T) {
+       h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
+       var payload []byte
+       _, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPduEmptyIEs, "%x", &payload)
+       if err != nil {
+               t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
+       }
+
+       xaction := []byte(RanName)
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
+       var rnibErr error
+       readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
+       ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RIC_TO_RAN)
+       rmrMessengerMock.On("SendMsg", ranRestartedMbuf).Return(&rmrCgo.MBuf{}, err)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf)
+}
 
-       payload, err := tests.BuildPackedX2ResetResponse()
+func TestX2ResetResponseShuttingDown(t *testing.T) {
+       h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
+       var payload []byte
+       _, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
        if err != nil {
-               t.Errorf("#x2_reset_response_handler_test.TestX2resetResponse - failed to build and pack X2ResetResponse. Error %x", err)
+               t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
        }
 
-       xaction := []byte("RanName")
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload),"RanName", &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
-               StartTime: time.Now(), TransactionId: string(xaction)}
-       var messageChannel chan<- *models.NotificationResponse
+       xaction := []byte(RanName)
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, NodeType: entities.Node_ENB}
+       var rnibErr error
+       readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
 
-       nb := &entities.NodebInfo{RanName:mBuf.Meid, ConnectionStatus:entities.ConnectionStatus_CONNECTED_SETUP_FAILED,}
+func TestX2ResetResponseInvalidConnectionStatus(t *testing.T) {
+       h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
+       var payload []byte
+       _, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
+       if err != nil {
+               t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
+       }
+
+       xaction := []byte(RanName)
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, NodeType: entities.Node_ENB}
        var rnibErr error
-       readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
+       readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
 
-       h.Handle(log, &notificationRequest, messageChannel)
+func TestX2ResetResponseError(t *testing.T) {
+       h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
+       var payload []byte
+       _, err := fmt.Sscanf(UnsuccessfulX2ResetResponsePackedPdu, "%x", &payload)
+       if err != nil {
+               t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
+       }
 
-       //TODO:Nothing to verify
+       xaction := []byte(RanName)
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
+       var rnibErr error
+       readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
-func TestX2ResetResponseReaderFailure(t *testing.T) {
-       log, h, readerMock := initX2ResetResponseHandlerTest(t)
+func TestX2ResetResponseGetNodebFailure(t *testing.T) {
+       h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
 
        var payload []byte
-       xaction := []byte("RanName")
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload),"RanName", &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
-               StartTime: time.Now(), TransactionId: string(xaction)}
-       var messageChannel chan<- *models.NotificationResponse
+       _, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
+       if err != nil {
+               t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
+       }
 
-       var nb *entities.NodebInfo
-       rnibErr  := common.NewResourceNotFoundError("nodeb not found")
-       readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
+       xaction := []byte(RanName)
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
 
-       h.Handle(log, &notificationRequest, messageChannel)
+       var nb *entities.NodebInfo
+       rnibErr := common.NewResourceNotFoundError("nodeb not found")
+       readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
 
-       //TODO:Nothing to verify
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
 
 func TestX2ResetResponseUnpackFailure(t *testing.T) {
-       log, h, readerMock := initX2ResetResponseHandlerTest(t)
+       h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
 
-       payload := []byte("not valid payload")
-       xaction := []byte("RanName")
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload),"RanName", &payload, &xaction)
-       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
-               StartTime: time.Now(), TransactionId: string(xaction)}
-       var messageChannel chan<- *models.NotificationResponse
-
-       nb := &entities.NodebInfo{RanName:mBuf.Meid, ConnectionStatus:entities.ConnectionStatus_CONNECTED_SETUP_FAILED,}
+       payload := []byte("Invalid payload")
+       xaction := []byte(RanName)
+       notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: string(xaction)}
+       nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
        var rnibErr error
-       readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
-
-       h.Handle(log, &notificationRequest, messageChannel)
+       readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
 
-       //TODO:Nothing to verify
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
 }
index 2f35925..77a09b3 100644 (file)
@@ -28,47 +28,58 @@ import (
        "e2mgr/logger"
        "e2mgr/models"
        "e2mgr/rmrCgo"
+       "e2mgr/services/rmrsender"
        "unsafe"
 )
 
-type X2EnbConfigurationUpdateHandler struct{}
+type X2EnbConfigurationUpdateHandler struct {
+       logger    *logger.Logger
+       rmrSender *rmrsender.RmrSender
+}
 
-func NewX2EnbConfigurationUpdateHandler() X2EnbConfigurationUpdateHandler {
-       return X2EnbConfigurationUpdateHandler{}
+func NewX2EnbConfigurationUpdateHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender) X2EnbConfigurationUpdateHandler {
+       return X2EnbConfigurationUpdateHandler{
+               logger:    logger,
+               rmrSender: rmrSender,
+       }
 }
 
-func (src X2EnbConfigurationUpdateHandler) Handle(logger *logger.Logger, request *models.NotificationRequest,
-       messageChannel chan<- *models.NotificationResponse) {
+func (h X2EnbConfigurationUpdateHandler) Handle(request *models.NotificationRequest) {
 
        var payloadSize C.ulong
        payloadSize = e2pdus.MaxAsn1PackedBufferSize
        packedBuffer := [e2pdus.MaxAsn1PackedBufferSize]C.uchar{}
        errorBuffer := [e2pdus.MaxAsn1PackedBufferSize]C.char{}
-       refinedMessage, err := converters.UnpackX2apPduAndRefine(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+
+       refinedMessage, err := converters.UnpackX2apPduAndRefine(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+
        if err != nil {
                status := C.build_pack_x2enb_configuration_update_failure(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
                if status {
                        payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
-                       logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update negative ack message payload: (%d) %02x", len(payload), payload)
-                       response := models.NotificationResponse{RanName: request.RanName, Payload: payload, MgsType: rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE}
-                       messageChannel <- &response
+                       h.logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update negative ack message payload: (%d) %02x", len(payload), payload)
+                       msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, request.RanName, payload)
+                       _ = h.rmrSender.Send(msg)
                } else {
-                       logger.Errorf("#x2enb_configuration_update_handler.Handle - failed to build and pack Enb configuration update unsuccessful outcome message. Error: %v", errorBuffer)
+                       h.logger.Errorf("#x2enb_configuration_update_handler.Handle - failed to build and pack Enb configuration update unsuccessful outcome message. Error: %v", errorBuffer)
                }
-               logger.Errorf("#x2enb_configuration_update_handler.Handle - unpack failed. Error: %v", err)
-       } else {
-               logger.Infof("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message received")
-               logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message payload: %s", refinedMessage.PduPrint)
+               h.logger.Errorf("#x2enb_configuration_update_handler.Handle - unpack failed. Error: %v", err)
 
-               status := C.build_pack_x2enb_configuration_update_ack(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
-               if status {
-                       payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
-                       logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update positive ack message payload: (%d) %02x", len(payload), payload)
-                       response := models.NotificationResponse{RanName: request.RanName, Payload: payload, MgsType: rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK}
-                       messageChannel <- &response
-               } else {
-                       logger.Errorf("#x2enb_configuration_update_handler.Handle - failed to build and pack enb configuration update successful outcome message. Error: %v", errorBuffer)
-               }
+               printHandlingSetupResponseElapsedTimeInMs(h.logger, "#x2enb_configuration_update_handler.Handle - Summary: Elapsed time for receiving and handling enb configuration update initiating message from E2 terminator", request.StartTime)
+               return
+       }
+
+       h.logger.Infof("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message received")
+       h.logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message payload: %s", refinedMessage.PduPrint)
+
+       status := C.build_pack_x2enb_configuration_update_ack(&payloadSize, &packedBuffer[0], e2pdus.MaxAsn1PackedBufferSize, &errorBuffer[0])
+       if status {
+               payload := (*[1 << 30]byte)(unsafe.Pointer(&packedBuffer))[:payloadSize:payloadSize]
+               h.logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update positive ack message payload: (%d) %02x", len(payload), payload)
+               msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, request.RanName, payload)
+               _ = h.rmrSender.Send(msg)
+       } else {
+               h.logger.Errorf("#x2enb_configuration_update_handler.Handle - failed to build and pack enb configuration update successful outcome message. Error: %v", errorBuffer)
        }
-       printHandlingSetupResponseElapsedTimeInMs(logger, "#x2enb_configuration_update_handler.Handle - Summary: Elapsed time for receiving and handling enb configuration update initiating message from E2 terminator", request.StartTime)
+       printHandlingSetupResponseElapsedTimeInMs(h.logger, "#x2enb_configuration_update_handler.Handle - Summary: Elapsed time for receiving and handling enb configuration update initiating message from E2 terminator", request.StartTime)
 }
index 7cb6b7d..30ba645 100644 (file)
 package rmrmsghandlers
 
 import (
-       "e2mgr/logger"
+       "e2mgr/mocks"
        "e2mgr/models"
        "e2mgr/rmrCgo"
-       "e2mgr/tests"
-       "github.com/stretchr/testify/assert"
+       "fmt"
        "testing"
        "time"
 )
 
-func TestHandleSuccessEnbConfigUpdate(t *testing.T){
-               log, err := logger.InitLogger(logger.InfoLevel)
-               if err!=nil{
-                       t.Errorf("#endc_configuration_update_handler_test.TestHandleSuccessEndcConfigUpdate - failed to initialize logger, error: %s", err)
-               }
-               h := X2EnbConfigurationUpdateHandler{}
+const PackedX2EnbConfigurationUpdateAck = "200800080000010011400100"
+const PackedX2EnbConfigurationUpdateFailure = "400800080000010005400142"
 
-               payload := tests.GetPackedPayload(t)
-               mBuf := rmrCgo.NewMBuf(10370, len(payload),"RanName", &payload, &tests.DummyXAction)
-               notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now()}
-               messageChannel := make(chan *models.NotificationResponse)
-
-               go h.Handle(log, &notificationRequest, messageChannel)
+func initX2EnbConfigurationUpdateHandlerTest(t *testing.T) (X2EnbConfigurationUpdateHandler, *mocks.RmrMessengerMock) {
+       log := initLog(t)
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, log)
+       h := NewX2EnbConfigurationUpdateHandler(log, rmrSender)
+       return h, rmrMessengerMock
+}
 
-               response := <-messageChannel
+func TestHandleX2EnbConfigUpdateSuccess(t *testing.T) {
+       h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
 
-               assert.NotEmpty(t, response)
-               assert.EqualValues(t, 10081, response.MgsType)
-               assert.True(t, len(response.Payload) > 0)
-}
+       ranName := "test"
+       xaction := []byte(ranName)
 
-func TestHandleFailureEnbConfigUpdate(t *testing.T){
-       log, err := logger.InitLogger(logger.InfoLevel)
-       if err!=nil{
-               t.Errorf("#endc_configuration_update_handler_test.TestHandleFailureEndcConfigUpdate - failed to initialize logger, error: %s", err)
-       }
-       h := X2EnbConfigurationUpdateHandler{}
+       var payload []byte
+       _, _ = fmt.Sscanf(PackedX2EnbConfigurationUpdateAck, "%x", &payload)
 
-       mBuf := rmrCgo.NewMBuf(tests.MessageType, 4,"RanName", &tests.DummyPayload, &tests.DummyXAction)
+       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, len(payload), ranName, &payload, &xaction)
        notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now()}
-       messageChannel := make(chan *models.NotificationResponse)
+       var err error
+       rmrMessengerMock.On("SendMsg", mBuf).Return(&rmrCgo.MBuf{}, err)
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+}
+
+func TestHandleX2EnbConfigUpdateFailure(t *testing.T) {
+       h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
 
-       go h.Handle(log, &notificationRequest, messageChannel)
+       ranName := "test"
+       xaction := []byte(ranName)
 
-       response := <-messageChannel
+       var payload []byte
+       _, _ = fmt.Sscanf(PackedX2EnbConfigurationUpdateFailure, "%x", &payload)
 
-       assert.NotEmpty(t, response)
-       assert.EqualValues(t, 10082, response.MgsType)
-       assert.True(t, len(response.Payload) > 0)
+       mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, len(payload), ranName, &payload, &xaction)
+       notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0}, StartTime: time.Now()}
+       rmrMessengerMock.On("SendMsg", mBuf).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
+       h.Handle(&notificationRequest)
+       rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
 }
diff --git a/E2Manager/httpserver/http_server.go b/E2Manager/httpserver/http_server.go
new file mode 100644 (file)
index 0000000..d6ade1e
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package httpserver
+
+import (
+       "e2mgr/controllers"
+       "fmt"
+       "github.com/gorilla/mux"
+       "log"
+       "net/http"
+)
+
+func Run(port int, controller controllers.IRootController, newController controllers.INodebController) {
+
+       router := mux.NewRouter();
+       initializeRoutes(router, controller, newController)
+
+       addr := fmt.Sprintf(":%d", port)
+
+       err := http.ListenAndServe(addr, router)
+
+       if err != nil {
+               log.Fatalf("#http_server.Run - Fail initiating HTTP server. Error: %v", err)
+       }
+}
+
+func initializeRoutes(router *mux.Router, rootController controllers.IRootController, nodebController controllers.INodebController) {
+       r := router.PathPrefix("/v1").Subrouter()
+       r.HandleFunc("/health", rootController.HandleHealthCheckRequest).Methods("GET")
+
+       rr := r.PathPrefix("/nodeb").Subrouter()
+       rr.HandleFunc("/ids", nodebController.GetNodebIdList).Methods("GET")
+       rr.HandleFunc("/{ranName}", nodebController.GetNodeb).Methods("GET")
+       rr.HandleFunc("/shutdown", nodebController.Shutdown).Methods("PUT")
+       rr.HandleFunc("/{ranName}/reset", nodebController.X2Reset).Methods("PUT")
+       rr.HandleFunc("/x2-setup", nodebController.X2Setup).Methods("POST")
+       rr.HandleFunc("/endc-setup", nodebController.EndcSetup).Methods("POST")
+}
diff --git a/E2Manager/httpserver/http_server_test.go b/E2Manager/httpserver/http_server_test.go
new file mode 100644 (file)
index 0000000..3d4d3d5
--- /dev/null
@@ -0,0 +1,156 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package httpserver
+
+import (
+       "e2mgr/mocks"
+       "github.com/gorilla/mux"
+       "github.com/stretchr/testify/assert"
+       "net/http"
+       "net/http/httptest"
+       "testing"
+)
+
+func setupRouterAndMocks() (*mux.Router, *mocks.ControllerMock, *mocks.NodebControllerMock) {
+       controllerMock := &mocks.ControllerMock{}
+       controllerMock.On("Shutdown").Return(nil)
+       controllerMock.On("X2Reset").Return(nil)
+       controllerMock.On("X2Setup").Return(nil)
+       controllerMock.On("EndcSetup").Return(nil)
+       controllerMock.On("GetNodeb").Return(nil)
+       controllerMock.On("GetNodebIdList").Return(nil)
+
+
+
+       nodebControllerMock := &mocks.NodebControllerMock{}
+       nodebControllerMock.On("GetNodebIdList").Return(nil)
+       nodebControllerMock.On("GetNodeb").Return(nil) // TODO: remove
+       nodebControllerMock.On("HandleHealthCheckRequest").Return(nil)
+
+       router := mux.NewRouter()
+       initializeRoutes(router, nodebControllerMock, controllerMock)
+       return router, controllerMock, nodebControllerMock
+}
+
+func TestRoutePostEndcSetup(t *testing.T) {
+       router, controllerMock, _ := setupRouterAndMocks()
+
+       req, err := http.NewRequest("POST", "/v1/nodeb/endc-setup", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       controllerMock.AssertNumberOfCalls(t,"EndcSetup", 1)
+}
+
+func TestRoutePostX2Setup(t *testing.T) {
+       router, controllerMock, _ := setupRouterAndMocks()
+
+       req, err := http.NewRequest("POST", "/v1/nodeb/x2-setup", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       controllerMock.AssertNumberOfCalls(t,"X2Setup", 1)
+}
+
+func TestRouteGetNodebIds(t *testing.T) {
+       router, controllerMock, _ := setupRouterAndMocks()
+
+       req, err := http.NewRequest("GET", "/v1/nodeb/ids", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       controllerMock.AssertNumberOfCalls(t, "GetNodebIdList", 1)
+}
+
+func TestRouteGetNodebRanName(t *testing.T) {
+       router, controllerMock,_ := setupRouterAndMocks()
+
+       req, err := http.NewRequest("GET", "/v1/nodeb/ran1", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       assert.Equal(t, http.StatusOK, rr.Code, "handler returned wrong status code")
+       assert.Equal(t, "ran1", rr.Body.String(), "handler returned wrong body")
+       controllerMock.AssertNumberOfCalls(t, "GetNodeb", 1)
+}
+
+func TestRouteGetHealth(t *testing.T) {
+       router, _, nodebControllerMock := setupRouterAndMocks()
+
+       req, err := http.NewRequest("GET", "/v1/health", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       nodebControllerMock.AssertNumberOfCalls(t, "HandleHealthCheckRequest", 1)
+}
+
+func TestRoutePutNodebShutdown(t *testing.T) {
+       router, controllerMock, _ := setupRouterAndMocks()
+
+       req, err := http.NewRequest("PUT", "/v1/nodeb/shutdown", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       controllerMock.AssertNumberOfCalls(t, "Shutdown", 1)
+}
+
+func TestRoutePutNodebResetRanName(t *testing.T) {
+       router, controllerMock, _ := setupRouterAndMocks()
+
+       req, err := http.NewRequest("PUT", "/v1/nodeb/ran1/reset", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       assert.Equal(t, http.StatusOK, rr.Code, "handler returned wrong status code")
+       assert.Equal(t, "ran1", rr.Body.String(), "handler returned wrong body")
+       controllerMock.AssertNumberOfCalls(t, "X2Reset", 1)
+}
+
+func TestRouteNotFound(t *testing.T) {
+       router, _, _ := setupRouterAndMocks()
+
+       req, err := http.NewRequest("GET", "/v1/no/such/route", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       assert.Equal(t, http.StatusNotFound, rr.Code, "handler returned wrong status code")
+}
\ No newline at end of file
diff --git a/E2Manager/main/http_server.go b/E2Manager/main/http_server.go
deleted file mode 100644 (file)
index 7cd6e39..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// 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.
-//
-
-package main
-
-import (
-       "e2mgr/configuration"
-       "e2mgr/controllers"
-       "e2mgr/logger"
-       "e2mgr/managers"
-       "e2mgr/managers/notificationmanager"
-       "e2mgr/models"
-       "e2mgr/rNibWriter"
-       "e2mgr/rmrCgo"
-       "e2mgr/services"
-       "e2mgr/services/receivers"
-       "fmt"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
-       "github.com/gorilla/mux"
-       "log"
-       "net/http"
-       "os"
-)
-
-const MAX_RNIB_POOL_INSTANCES = 4
-
-func main() {
-       config := configuration.ParseConfiguration()
-       logLevel, _ := logger.LogLevelTokenToLevel(config.Logging.LogLevel)
-       logger, err := logger.InitLogger(logLevel)
-       if err != nil {
-               fmt.Printf("#http_server.main - failed to initialize logger, error: %s", err)
-               os.Exit(1)
-       }
-       rmrConfig := services.NewRmrConfig(config.Rmr.Port, config.Rmr.MaxMsgSize, 0, logger)
-       var msgImpl *rmrCgo.Context
-       rNibWriter.Init("e2Manager", MAX_RNIB_POOL_INSTANCES)
-       defer rNibWriter.Close()
-       reader.Init("e2Manager", MAX_RNIB_POOL_INSTANCES)
-       defer reader.Close()
-
-       rnibDataService := services.NewRnibDataService(logger, config, reader.GetRNibReader, rNibWriter.GetRNibWriter)
-       rmrResponseChannel := make(chan *models.NotificationResponse, config.NotificationResponseBuffer)
-       rmrService := services.NewRmrService(rmrConfig, msgImpl, rmrResponseChannel)
-       var ranSetupManager = managers.NewRanSetupManager(logger, rmrService, rnibDataService)
-       var ranReconnectionManager = managers.NewRanReconnectionManager(logger, config, rnibDataService, ranSetupManager)
-       var nManager = notificationmanager.NewNotificationManager(rnibDataService, ranReconnectionManager)
-
-       rmrServiceReceiver := receivers.NewRmrServiceReceiver(*rmrService, nManager)
-       defer rmrService.CloseContext()
-       go rmrServiceReceiver.ListenAndHandle()
-       go rmrService.SendResponse()
-
-       controller := controllers.NewNodebController(logger, rmrService, rnibDataService)
-       newController := controllers.NewController(logger, rmrService, rnibDataService, config, ranSetupManager)
-       runServer(config.Http.Port, controller, newController)
-}
-
-func runServer(port int, controller controllers.INodebController, newController controllers.IController) {
-
-       router := mux.NewRouter();
-       initializeRoutes(router, controller, newController)
-
-       addr := fmt.Sprintf(":%d", port)
-       if err := http.ListenAndServe(addr, router); err != nil {
-               log.Fatalf("#runNodebServer - fail to start http server. Error: %v", err)
-       }
-}
-
-func initializeRoutes(router *mux.Router, controller controllers.INodebController, newController controllers.IController) {
-       r := router.PathPrefix("/v1").Subrouter()
-       r.HandleFunc("/health", controller.HandleHealthCheckRequest).Methods("GET")
-
-       rr := r.PathPrefix("/nodeb").Subrouter()
-       rr.HandleFunc("/ids", controller.GetNodebIdList).Methods("GET") // nodeb/ids
-       rr.HandleFunc("/{ranName}", controller.GetNodeb).Methods("GET")
-       rr.HandleFunc("/shutdown", newController.ShutdownHandler).Methods("PUT")
-       rr.HandleFunc("/{ranName}/reset", newController.X2ResetHandler).Methods("PUT") // nodeb/{ranName}/reset
-       rr.HandleFunc("/x2-setup", newController.X2SetupHandler).Methods("POST")
-       rr.HandleFunc("/endc-setup", newController.EndcSetupHandler).Methods("POST")
-}
diff --git a/E2Manager/main/http_server_test.go b/E2Manager/main/http_server_test.go
deleted file mode 100644 (file)
index 760274d..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// 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.
-//
-
-package main
-
-import (
-       "e2mgr/configuration"
-       "e2mgr/mocks"
-       "github.com/gorilla/mux"
-       "github.com/stretchr/testify/assert"
-       "gopkg.in/yaml.v2"
-       "io/ioutil"
-       "net/http"
-       "net/http/httptest"
-       "os"
-       "testing"
-)
-
-func setupRouterAndMocks() (*mux.Router, *mocks.ControllerMock, *mocks.NodebControllerMock) {
-       controllerMock := &mocks.ControllerMock{}
-       controllerMock.On("ShutdownHandler").Return(nil)
-       controllerMock.On("X2ResetHandler").Return(nil)
-       controllerMock.On("X2SetupHandler").Return(nil)
-       controllerMock.On("EndcSetupHandler").Return(nil)
-
-       nodebControllerMock := &mocks.NodebControllerMock{}
-       nodebControllerMock.On("GetNodebIdList").Return(nil)
-       nodebControllerMock.On("GetNodeb").Return(nil)
-       nodebControllerMock.On("HandleHealthCheckRequest").Return(nil)
-
-       router := mux.NewRouter()
-       initializeRoutes(router, nodebControllerMock, controllerMock)
-       return router, controllerMock, nodebControllerMock
-}
-
-func TestRoutePostEndcSetup(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
-
-       req, err := http.NewRequest("POST", "/v1/nodeb/endc-setup", nil)
-       if err != nil {
-               t.Fatal(err)
-       }
-       rr := httptest.NewRecorder()
-       router.ServeHTTP(rr, req)
-
-       controllerMock.AssertNumberOfCalls(t,"EndcSetupHandler", 1)
-}
-
-func TestRoutePostX2Setup(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
-
-       req, err := http.NewRequest("POST", "/v1/nodeb/x2-setup", nil)
-       if err != nil {
-               t.Fatal(err)
-       }
-       rr := httptest.NewRecorder()
-       router.ServeHTTP(rr, req)
-
-       controllerMock.AssertNumberOfCalls(t,"X2SetupHandler", 1)
-}
-
-func TestRouteGetNodebIds(t *testing.T) {
-       router, _, nodebControllerMock := setupRouterAndMocks()
-
-       req, err := http.NewRequest("GET", "/v1/nodeb/ids", nil)
-       if err != nil {
-               t.Fatal(err)
-       }
-       rr := httptest.NewRecorder()
-       router.ServeHTTP(rr, req)
-
-       nodebControllerMock.AssertNumberOfCalls(t, "GetNodebIdList", 1)
-}
-
-func TestRouteGetNodebRanName(t *testing.T) {
-       router, _, nodebControllerMock := setupRouterAndMocks()
-
-       req, err := http.NewRequest("GET", "/v1/nodeb/ran1", nil)
-       if err != nil {
-               t.Fatal(err)
-       }
-       rr := httptest.NewRecorder()
-       router.ServeHTTP(rr, req)
-
-       assert.Equal(t, http.StatusOK, rr.Code, "handler returned wrong status code")
-       assert.Equal(t, "ran1", rr.Body.String(), "handler returned wrong body")
-       nodebControllerMock.AssertNumberOfCalls(t, "GetNodeb", 1)
-}
-
-func TestRouteGetHealth(t *testing.T) {
-       router, _, nodebControllerMock := setupRouterAndMocks()
-
-       req, err := http.NewRequest("GET", "/v1/health", nil)
-       if err != nil {
-               t.Fatal(err)
-       }
-       rr := httptest.NewRecorder()
-       router.ServeHTTP(rr, req)
-
-       nodebControllerMock.AssertNumberOfCalls(t, "HandleHealthCheckRequest", 1)
-}
-
-func TestRoutePutNodebShutdown(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
-
-       req, err := http.NewRequest("PUT", "/v1/nodeb/shutdown", nil)
-       if err != nil {
-               t.Fatal(err)
-       }
-       rr := httptest.NewRecorder()
-       router.ServeHTTP(rr, req)
-
-       controllerMock.AssertNumberOfCalls(t, "ShutdownHandler", 1)
-}
-
-func TestRoutePutNodebResetRanName(t *testing.T) {
-       router, controllerMock, _ := setupRouterAndMocks()
-
-       req, err := http.NewRequest("PUT", "/v1/nodeb/ran1/reset", nil)
-       if err != nil {
-               t.Fatal(err)
-       }
-       rr := httptest.NewRecorder()
-       router.ServeHTTP(rr, req)
-
-       assert.Equal(t, http.StatusOK, rr.Code, "handler returned wrong status code")
-       assert.Equal(t, "ran1", rr.Body.String(), "handler returned wrong body")
-       controllerMock.AssertNumberOfCalls(t, "X2ResetHandler", 1)
-}
-
-func TestRouteNotFound(t *testing.T) {
-       router, _, _ := setupRouterAndMocks()
-
-       req, err := http.NewRequest("GET", "/v1/no/such/route", nil)
-       if err != nil {
-               t.Fatal(err)
-       }
-       rr := httptest.NewRecorder()
-       router.ServeHTTP(rr, req)
-
-       assert.Equal(t, http.StatusNotFound, rr.Code, "handler returned wrong status code")
-}
-
-func TestParseConfigurationSuccess(t *testing.T) {
-       config := configuration.ParseConfiguration()
-       assert.Equal(t, 3800, config.Http.Port)
-       assert.Equal(t, 3801, config.Rmr.Port)
-       assert.Equal(t, 4096, config.Rmr.MaxMsgSize)
-       assert.Equal(t, "info", config.Logging.LogLevel)
-       assert.Equal(t, 100, config.NotificationResponseBuffer)
-       assert.Equal(t, 5, config.BigRedButtonTimeoutSec)
-}
-
-func TestParseConfigurationFileNotFoundFailure(t *testing.T) {
-       configPath := "../resources/configuration.yaml"
-       configPathTmp := "../resources/configuration.yaml_tmp"
-       err := os.Rename(configPath, configPathTmp)
-       if err != nil {
-               t.Errorf("#http_server_test.TestParseConfigurationFileNotFoundFailure - failed to rename configuration file: %s\n", configPath)
-       }
-       defer func() {
-               err = os.Rename(configPathTmp, configPath)
-               if err != nil {
-                       t.Errorf("#http_server_test.TestParseConfigurationFileNotFoundFailure - failed to rename configuration file: %s\n", configPath)
-               }
-       }()
-       assert.Panics(t, func() { configuration.ParseConfiguration() })
-}
-
-func TestRmrConfigNotFoundFailure(t *testing.T) {
-       configPath := "../resources/configuration.yaml"
-       configPathTmp := "../resources/configuration.yaml_tmp"
-       err := os.Rename(configPath, configPathTmp)
-       if err != nil {
-               t.Errorf("#http_server_test.TestRmrConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
-       }
-       defer func() {
-               err = os.Rename(configPathTmp, configPath)
-               if err != nil {
-                       t.Errorf("#http_server_test.TestRmrConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
-               }
-       }()
-       yamlMap := map[string]interface{}{
-               "logging": map[string]interface{}{"logLevel": "info"},
-               "http":    map[string]interface{}{"port": 3800},
-       }
-       buf, err := yaml.Marshal(yamlMap)
-       if err != nil {
-               t.Errorf("#http_server_test.TestRmrConfigNotFoundFailure - failed to marshal configuration map\n")
-       }
-       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
-       if err != nil {
-               t.Errorf("#http_server_test.TestRmrConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
-       }
-       assert.PanicsWithValue(t, "#http_server.fillRmrConfig - failed to fill RMR configuration: The entry 'rmr' not found\n", func() { configuration.ParseConfiguration() })
-}
-
-func TestLoggingConfigNotFoundFailure(t *testing.T) {
-       configPath := "../resources/configuration.yaml"
-       configPathTmp := "../resources/configuration.yaml_tmp"
-       err := os.Rename(configPath, configPathTmp)
-       if err != nil {
-               t.Errorf("#http_server_test.TestLoggingConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
-       }
-       defer func() {
-               err = os.Rename(configPathTmp, configPath)
-               if err != nil {
-                       t.Errorf("#http_server_test.TestLoggingConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
-               }
-       }()
-       yamlMap := map[string]interface{}{
-               "rmr":  map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
-               "http": map[string]interface{}{"port": 3800},
-       }
-       buf, err := yaml.Marshal(yamlMap)
-       if err != nil {
-               t.Errorf("#http_server_test.TestRmrConfigNotFoundFailure - failed to marshal configuration map\n")
-       }
-       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
-       if err != nil {
-               t.Errorf("#http_server_test.TestRmrConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
-       }
-       assert.PanicsWithValue(t, "#http_server.fillLoggingConfig - failed to fill logging configuration: The entry 'logging' not found\n",
-               func() { configuration.ParseConfiguration() })
-}
-
-func TestHttpConfigNotFoundFailure(t *testing.T) {
-       configPath := "../resources/configuration.yaml"
-       configPathTmp := "../resources/configuration.yaml_tmp"
-       err := os.Rename(configPath, configPathTmp)
-       if err != nil {
-               t.Errorf("#http_server_test.TestHttpConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
-       }
-       defer func() {
-               err = os.Rename(configPathTmp, configPath)
-               if err != nil {
-                       t.Errorf("#http_server_test.TestHttpConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
-               }
-       }()
-       yamlMap := map[string]interface{}{
-               "rmr":     map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
-               "logging": map[string]interface{}{"logLevel": "info"},
-       }
-       buf, err := yaml.Marshal(yamlMap)
-       if err != nil {
-               t.Errorf("#http_server_test.TestHttpConfigNotFoundFailure - failed to marshal configuration map\n")
-       }
-       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
-       if err != nil {
-               t.Errorf("#http_server_test.TestHttpConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
-       }
-       assert.PanicsWithValue(t, "#http_server.fillHttpConfig - failed to fill HTTP configuration: The entry 'http' not found\n",
-               func() { configuration.ParseConfiguration() })
-}
index 70b81ed..12250d2 100644 (file)
@@ -19,37 +19,34 @@ package notificationmanager
 
 import (
        "e2mgr/logger"
-       "e2mgr/managers"
        "e2mgr/models"
        "e2mgr/providers/rmrmsghandlerprovider"
        "e2mgr/rmrCgo"
-       "e2mgr/services"
-       "fmt"
        "time"
 )
 
 type NotificationManager struct {
+       logger                      *logger.Logger
        notificationHandlerProvider *rmrmsghandlerprovider.NotificationHandlerProvider
 }
 
-func NewNotificationManager(rnibDataService services.RNibDataService, ranReconnectionManager *managers.RanReconnectionManager) *NotificationManager {
-       notificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider(rnibDataService, ranReconnectionManager)
-
+func NewNotificationManager(logger *logger.Logger, notificationHandlerProvider *rmrmsghandlerprovider.NotificationHandlerProvider) *NotificationManager {
        return &NotificationManager{
+               logger:                      logger,
                notificationHandlerProvider: notificationHandlerProvider,
        }
 }
 
-//TODO add NEWHandler with log
-func (m NotificationManager) HandleMessage(logger *logger.Logger, mbuf *rmrCgo.MBuf, responseChannel chan<- *models.NotificationResponse) {
+func (m NotificationManager) HandleMessage(mbuf *rmrCgo.MBuf) error {
 
        notificationHandler, err := m.notificationHandlerProvider.GetNotificationHandler(mbuf.MType)
 
        if err != nil {
-               logger.Errorf(fmt.Sprintf("%s", err))
-               return
+               m.logger.Errorf("#NotificationManager.HandleMessage - Error: %s", err)
+               return err
        }
 
        notificationRequest := models.NewNotificationRequest(mbuf.Meid, *mbuf.Payload, time.Now(), string(*mbuf.XAction))
-       go notificationHandler.Handle(logger, notificationRequest, responseChannel)
+       go notificationHandler.Handle(notificationRequest)
+       return nil
 }
diff --git a/E2Manager/managers/notificationmanager/notification_manager_test.go b/E2Manager/managers/notificationmanager/notification_manager_test.go
new file mode 100644 (file)
index 0000000..770ed02
--- /dev/null
@@ -0,0 +1,82 @@
+package notificationmanager
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/converters"
+       "e2mgr/logger"
+       "e2mgr/managers"
+       "e2mgr/mocks"
+       "e2mgr/providers/rmrmsghandlerprovider"
+       "e2mgr/rNibWriter"
+       "e2mgr/rmrCgo"
+       "e2mgr/services"
+       "e2mgr/services/rmrsender"
+       "e2mgr/tests"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func initNotificationManagerTest(t *testing.T) (*logger.Logger, *mocks.RnibReaderMock, *NotificationManager) {
+       logger := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+
+       readerMock := &mocks.RnibReaderMock{}
+       rnibReaderProvider := func() reader.RNibReader {
+               return readerMock
+       }
+       writerMock := &mocks.RnibWriterMock{}
+       rnibWriterProvider := func() rNibWriter.RNibWriter {
+               return writerMock
+       }
+
+       rmrSender := initRmrSender(&mocks.RmrMessengerMock{}, logger)
+       rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
+       ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
+       ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
+       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
+       x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
+       x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter)
+       x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
+       x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
+       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager)
+       notificationManager := NewNotificationManager(logger, rmrNotificationHandlerProvider )
+       return logger, readerMock, notificationManager
+}
+
+func TestHandleMessageUnexistingMessageType(t *testing.T) {
+       _, _, nm := initNotificationManagerTest(t)
+
+       mbuf := &rmrCgo.MBuf{MType: 1234}
+
+       err := nm.HandleMessage(mbuf)
+       assert.NotNil(t, err)
+}
+
+func TestHandleMessageExistingMessageType(t *testing.T) {
+       _, readerMock, nm := initNotificationManagerTest(t)
+       payload := []byte("123")
+       xaction := []byte("test")
+       mbuf := &rmrCgo.MBuf{MType: rmrCgo.RIC_X2_SETUP_RESP, Meid: "test", Payload: &payload, XAction: &xaction}
+       readerMock.On("GetNodeb", "test").Return(&entities.NodebInfo{}, fmt.Errorf("Some error"))
+       err := nm.HandleMessage(mbuf)
+       assert.Nil(t, err)
+}
+
+// TODO: extract to test_utils
+func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
+       rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
+       rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
+       return rmrsender.NewRmrSender(log, &rmrMessenger)
+}
+
+// TODO: extract to test_utils
+func initLog(t *testing.T) *logger.Logger {
+       log, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
+       }
+       return log
+}
index d8e169d..3aeeeed 100644 (file)
@@ -21,10 +21,10 @@ import (
        "e2mgr/configuration"
        "e2mgr/logger"
        "e2mgr/mocks"
-       "e2mgr/models"
        "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
@@ -43,7 +43,7 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessenge
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
        rmrMessengerMock := &mocks.RmrMessengerMock{}
-       rmrService := getRmrService(rmrMessengerMock, logger)
+       rmrSender := initRmrSender(rmrMessengerMock, logger)
 
        readerMock := &mocks.RnibReaderMock{}
        rnibReaderProvider := func() reader.RNibReader {
@@ -54,7 +54,7 @@ func initRanLostConnectionTest(t *testing.T) (*logger.Logger, *mocks.RmrMessenge
                return writerMock
        }
        rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
-       ranSetupManager := NewRanSetupManager(logger, rmrService, rnibDataService)
+       ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService)
        ranReconnectionManager := NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
        return logger, rmrMessengerMock, readerMock, writerMock, ranReconnectionManager
 }
@@ -137,7 +137,7 @@ func TestConnectedRanExecuteSetupSuccess(t *testing.T) {
        updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTING
        updatedNodebInfo.ConnectionAttempts++
        writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil)
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.AnythingOfType("int")).Return(&rmrCgo.MBuf{}, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(&rmrCgo.MBuf{}, nil)
        err := ranReconnectionManager.ReconnectRan(ranName)
        assert.Nil(t, err)
        readerMock.AssertCalled(t, "GetNodeb", ranName)
@@ -161,10 +161,8 @@ func TestConnectedRanExecuteSetupFailure(t *testing.T) {
        writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
 }
 
-// TODO: should extract to test_utils
-func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService {
+func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       messageChannel := make(chan *models.NotificationResponse)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, messageChannel)
+       return rmrsender.NewRmrSender(log, &rmrMessenger)
 }
index 7500069..35908a7 100644 (file)
@@ -24,20 +24,21 @@ import (
        "e2mgr/models"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
 type RanSetupManager struct {
-       logger             *logger.Logger
+       logger          *logger.Logger
        rnibDataService services.RNibDataService
-       rmrService         *services.RmrService
+       rmrSender       *rmrsender.RmrSender
 }
 
-func NewRanSetupManager(logger *logger.Logger, rmrService *services.RmrService, rnibDataService services.RNibDataService) *RanSetupManager {
+func NewRanSetupManager(logger *logger.Logger, rmrSender *rmrsender.RmrSender, rnibDataService services.RNibDataService) *RanSetupManager {
        return &RanSetupManager{
-               logger:             logger,
+               logger:          logger,
                rnibDataService: rnibDataService,
-               rmrService:         rmrService,
+               rmrSender:       rmrSender,
        }
 }
 
@@ -101,12 +102,17 @@ func (m *RanSetupManager) ExecuteSetup(nodebInfo *entities.NodebInfo, status ent
        }
 
        // Send the endc/x2 setup request
-       response := &models.NotificationResponse{MgsType: rmrMsgType, RanName: nodebInfo.RanName, Payload: request.GetMessageAsBytes(m.logger)}
-       if err := m.rmrService.SendRmrMessage(response); err != nil {
+       msg := models.NewRmrMessage(rmrMsgType, nodebInfo.RanName, request.GetMessageAsBytes(m.logger))
+
+       err = m.rmrSender.Send(msg)
+
+       if err != nil {
                m.logger.Errorf("#RanSetupManager.ExecuteSetup - failed sending setup request to RMR: %s", err)
 
+               err := m.updateConnectionStatusDisconnected(nodebInfo)
+
                // Decrement retries and connection status (disconnected)
-               if err := m.updateConnectionStatusDisconnected(nodebInfo); err != nil {
+               if err != nil {
                        return e2managererrors.NewRnibDbError()
                }
 
index 20f3d59..1b31c4c 100644 (file)
@@ -43,7 +43,7 @@ func initRanSetupManagerTest(t *testing.T) (*mocks.RmrMessengerMock, *mocks.Rnib
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
        rmrMessengerMock := &mocks.RmrMessengerMock{}
-       rmrService := getRmrService(rmrMessengerMock, logger)
+       rmrSender := initRmrSender(rmrMessengerMock, logger)
 
        readerMock := &mocks.RnibReaderMock{}
        rnibReaderProvider := func() reader.RNibReader {
@@ -54,7 +54,7 @@ func initRanSetupManagerTest(t *testing.T) (*mocks.RmrMessengerMock, *mocks.Rnib
                return writerMock
        }
        rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
-       ranSetupManager := NewRanSetupManager(logger, rmrService, rnibDataService)
+       ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService)
        return rmrMessengerMock, writerMock, ranSetupManager
 }
 
@@ -71,7 +71,7 @@ func TestExecuteSetupConnectingX2Setup(t *testing.T) {
        payload := e2pdus.PackedX2setupRequest
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err != nil {
                t.Errorf("want: success, got: error: %s", err)
@@ -94,7 +94,7 @@ func TestExecuteSetupConnectingEndcX2Setup(t *testing.T) {
        payload := e2pdus.PackedEndcX2setupRequest
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err != nil {
                t.Errorf("want: success, got: error: %s", err)
@@ -119,7 +119,7 @@ func TestExecuteSetupDisconnected(t *testing.T) {
        payload := []byte{0}
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, fmt.Errorf("send failure"))
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, fmt.Errorf("send failure"))
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
                t.Errorf("want: failure, got: success")
@@ -144,7 +144,7 @@ func TestExecuteSetupConnectingRnibError(t *testing.T) {
        payload := []byte{0}
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, fmt.Errorf("send failure"))
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, fmt.Errorf("send failure"))
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
                t.Errorf("want: failure, got: success")
@@ -171,7 +171,7 @@ func TestExecuteSetupDisconnectedRnibError(t *testing.T) {
        payload := []byte{0}
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, fmt.Errorf("send failure"))
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, fmt.Errorf("send failure"))
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
                t.Errorf("want: failure, got: success")
@@ -196,7 +196,7 @@ func TestExecuteSetupUnsupportedProtocol(t *testing.T) {
        payload := e2pdus.PackedX2setupRequest
        xaction := []byte(ranName)
        msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
 
        if err := mgr.ExecuteSetup(initialNodeb, entities.ConnectionStatus_CONNECTING); err == nil {
                t.Errorf("want: error, got: success")
diff --git a/E2Manager/managers/ran_status_change_manager.go b/E2Manager/managers/ran_status_change_manager.go
new file mode 100644 (file)
index 0000000..153255a
--- /dev/null
@@ -0,0 +1,40 @@
+package managers
+
+import (
+       "e2mgr/enums"
+       "e2mgr/logger"
+       "e2mgr/models"
+       "e2mgr/services/rmrsender"
+       "encoding/json"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+)
+
+type RanStatusChangeManager struct {
+       logger    *logger.Logger
+       rmrSender *rmrsender.RmrSender
+}
+
+func NewRanStatusChangeManager(logger *logger.Logger, rmrSender *rmrsender.RmrSender) *RanStatusChangeManager {
+       return &RanStatusChangeManager{
+               logger:    logger,
+               rmrSender: rmrSender,
+       }
+}
+
+type IRanStatusChangeManager interface {
+       Execute(msgType int, msgDirection enums.MessageDirection, nodebInfo *entities.NodebInfo) error
+}
+
+func (m *RanStatusChangeManager) Execute(msgType int, msgDirection enums.MessageDirection, nodebInfo *entities.NodebInfo) error {
+
+       resourceStatusPayload := models.NewResourceStatusPayload(nodebInfo.NodeType, msgDirection)
+       resourceStatusJson, err := json.Marshal(resourceStatusPayload)
+
+       if err != nil {
+               m.logger.Errorf("#RanStatusChangeManager.Execute - RAN name: %s - Error marshaling resource status payload: %v", nodebInfo.RanName, err)
+               return err
+       }
+
+       rmrMessage := models.NewRmrMessage(msgType, nodebInfo.RanName, resourceStatusJson)
+       return m.rmrSender.Send(rmrMessage)
+}
diff --git a/E2Manager/managers/ran_status_change_manager_test.go b/E2Manager/managers/ran_status_change_manager_test.go
new file mode 100644 (file)
index 0000000..be8642e
--- /dev/null
@@ -0,0 +1,47 @@
+package managers
+
+import (
+       "e2mgr/enums"
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "e2mgr/rmrCgo"
+       "e2mgr/services/rmrsender"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
+       "testing"
+)
+
+func initRanStatusChangeManagerTest(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock, *rmrsender.RmrSender) {
+       logger, err := logger.InitLogger(logger.DebugLevel)
+       if err != nil {
+               t.Fatalf("#initStatusChangeManagerTest - failed to initialize logger, error: %s", err)
+       }
+
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrSender := initRmrSender(rmrMessengerMock, logger)
+
+       return logger, rmrMessengerMock, rmrSender
+}
+
+func TestMarshalFailure(t *testing.T) {
+       logger, _, rmrSender := initRanStatusChangeManagerTest(t)
+       m := NewRanStatusChangeManager(logger, rmrSender)
+
+       nodebInfo := entities.NodebInfo{}
+       err := m.Execute(123, 4, &nodebInfo)
+
+       assert.NotNil(t, err)
+}
+
+func TestMarshalSuccess(t *testing.T) {
+       logger, rmrMessengerMock, rmrSender := initRanStatusChangeManagerTest(t)
+       m := NewRanStatusChangeManager(logger, rmrSender)
+
+       nodebInfo := entities.NodebInfo{NodeType: entities.Node_ENB}
+       var err error
+       rmrMessengerMock.On("SendMsg", mock.Anything).Return(&rmrCgo.MBuf{}, err)
+       err  = m.Execute(rmrCgo.RAN_CONNECTED, enums.RIC_TO_RAN, &nodebInfo)
+
+       assert.Nil(t, err)
+}
index f30c394..7f41b91 100644 (file)
@@ -19,20 +19,23 @@ package managers
 
 import (
        "e2mgr/converters"
-       "e2mgr/e2pdus"
        "e2mgr/logger"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
-type X2SetupFailureResponseManager struct{}
+type X2SetupFailureResponseManager struct {
+       converter converters.IX2SetupFailureResponseConverter
+}
 
-func NewX2SetupFailureResponseManager() *X2SetupFailureResponseManager {
-       return &X2SetupFailureResponseManager{}
+func NewX2SetupFailureResponseManager(converter converters.IX2SetupFailureResponseConverter) *X2SetupFailureResponseManager {
+       return &X2SetupFailureResponseManager{
+               converter: converter,
+       }
 }
 
 func (m *X2SetupFailureResponseManager) PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error {
 
-       failureResponse, err := converters.UnpackX2SetupFailureResponseAndExtract(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+       failureResponse, err := m.converter.UnpackX2SetupFailureResponseAndExtract(payload)
 
        if err != nil {
                logger.Errorf("#X2SetupFailureResponseManager.PopulateNodebByPdu - RAN name: %s - Unpack and extract failed. Error: %v", nodebInfo.RanName, err)
index 0364078..a9ac2ad 100644 (file)
@@ -19,20 +19,23 @@ package managers
 
 import (
        "e2mgr/converters"
-       "e2mgr/e2pdus"
        "e2mgr/logger"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
-type X2SetupResponseManager struct{}
+type X2SetupResponseManager struct {
+       converter converters.IX2SetupResponseConverter
+}
 
-func NewX2SetupResponseManager() *X2SetupResponseManager {
-       return &X2SetupResponseManager{}
+func NewX2SetupResponseManager(converter converters.IX2SetupResponseConverter) *X2SetupResponseManager {
+       return &X2SetupResponseManager{
+               converter: converter,
+       }
 }
 
 func (m *X2SetupResponseManager) PopulateNodebByPdu(logger *logger.Logger, nbIdentity *entities.NbIdentity, nodebInfo *entities.NodebInfo, payload []byte) error {
 
-       enbId, enb, err := converters.UnpackX2SetupResponseAndExtract(logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+       enbId, enb, err := m.converter.UnpackX2SetupResponseAndExtract(payload)
 
        if err != nil {
                logger.Errorf("#X2SetupResponseManager.PopulateNodebByPdu - RAN name: %s - Unpack and extract failed. %v", nodebInfo.RanName, err)
index 5393a55..7575f72 100644 (file)
@@ -10,11 +10,28 @@ type ControllerMock struct {
        mock.Mock
 }
 
-func (c *ControllerMock) ShutdownHandler(writer http.ResponseWriter, r *http.Request){
+func (c *ControllerMock) GetNodeb(writer http.ResponseWriter, r *http.Request){
+               writer.Header().Set("Content-Type", "application/json")
+               writer.WriteHeader(http.StatusOK)
+
+               vars := mux.Vars(r)
+               ranName := vars["ranName"]
+
+               writer.Write([]byte(ranName))
+
+               c.Called()
+}
+
+func (c *ControllerMock) GetNodebIdList(writer http.ResponseWriter, r *http.Request){
+       c.Called()
+}
+
+
+func (c *ControllerMock) Shutdown(writer http.ResponseWriter, r *http.Request){
        c.Called()
 }
 
-func (c *ControllerMock) X2ResetHandler(writer http.ResponseWriter, r *http.Request){
+func (c *ControllerMock) X2Reset(writer http.ResponseWriter, r *http.Request){
        writer.Header().Set("Content-Type", "application/json")
        writer.WriteHeader(http.StatusOK)
 
@@ -26,14 +43,14 @@ func (c *ControllerMock) X2ResetHandler(writer http.ResponseWriter, r *http.Requ
        c.Called()
 }
 
-func (c *ControllerMock) X2SetupHandler(writer http.ResponseWriter, r *http.Request){
+func (c *ControllerMock) X2Setup(writer http.ResponseWriter, r *http.Request){
        writer.Header().Set("Content-Type", "application/json")
        writer.WriteHeader(http.StatusOK)
 
        c.Called()
 }
 
-func (c *ControllerMock) EndcSetupHandler(writer http.ResponseWriter, r *http.Request){
+func (c *ControllerMock) EndcSetup(writer http.ResponseWriter, r *http.Request){
        writer.Header().Set("Content-Type", "application/json")
        writer.WriteHeader(http.StatusOK)
 
index ff6c71f..dc4fa15 100644 (file)
@@ -32,13 +32,13 @@ func (m *RmrMessengerMock) Init(port string, maxMsgSize int, flags int, logger *
        return args.Get(0).(*rmrCgo.RmrMessenger)
 }
 
-func (m *RmrMessengerMock) SendMsg(msg *rmrCgo.MBuf, maxMsgSize int) (*rmrCgo.MBuf, error){
-       args := m.Called(msg, maxMsgSize)
+func (m *RmrMessengerMock) SendMsg(msg *rmrCgo.MBuf) (*rmrCgo.MBuf, error){
+       args := m.Called(msg)
        return args.Get(0).(*rmrCgo.MBuf), args.Error(1)
 }
 
 func (m *RmrMessengerMock) RecvMsg() (*rmrCgo.MBuf, error){
-       args := m.Called( )
+       args := m.Called()
        return args.Get(0).(*rmrCgo.MBuf), args.Error(1)
 }
 
index 3ac82cc..d8aa697 100644 (file)
@@ -42,10 +42,9 @@ func NewE2RequestMessage(transactionId string, ranIp string, ranPort uint16, ran
        return &E2RequestMessage{transactionId: transactionId, ranIp: ranIp, ranPort: ranPort, ranName: ranName, payload: payload}
 }
 
+// TODO: this shouldn't receive logger
 func (e2RequestMessage E2RequestMessage) GetMessageAsBytes(logger *logger.Logger) []byte {
-       messageStringWithoutPayload := fmt.Sprintf("%s|%d|%s|%d|", e2RequestMessage.ranIp,
-               e2RequestMessage.ranPort, e2RequestMessage.ranName,
-               len(e2RequestMessage.payload))
+       messageStringWithoutPayload := fmt.Sprintf("%s|%d|%s|%d|", e2RequestMessage.ranIp, e2RequestMessage.ranPort, e2RequestMessage.ranName, len(e2RequestMessage.payload))
        logger.Debugf("#e2_request_message.GetMessageAsBytes - messageStringWithoutPayload: %s", messageStringWithoutPayload)
        messageBytesWithoutPayload := []byte(messageStringWithoutPayload)
        return append(messageBytesWithoutPayload, e2RequestMessage.payload...)
diff --git a/E2Manager/models/get_nodeb_id_list_response.go b/E2Manager/models/get_nodeb_id_list_response.go
new file mode 100644 (file)
index 0000000..03f095d
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package models
+
+import (
+       "e2mgr/e2managererrors"
+       "e2mgr/utils"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+)
+
+type GetNodebIdListResponse struct {
+       nodebIdList []*entities.NbIdentity
+}
+
+func NewGetNodebIdListResponse(nodebIdList []*entities.NbIdentity) *GetNodebIdListResponse {
+       return &GetNodebIdListResponse{
+               nodebIdList: nodebIdList,
+       }
+}
+
+func (response *GetNodebIdListResponse) Marshal() (string, error) {
+       pmList := utils.ConvertNodebIdListToProtoMessageList(response.nodebIdList)
+       result, err := utils.MarshalProtoMessageListToJsonArray(pmList)
+
+       if err != nil {
+               return "", e2managererrors.NewInternalError();
+       }
+
+       return result, nil
+}
similarity index 73%
rename from E2Manager/models/notification_response.go
rename to E2Manager/models/get_nodeb_request.go
index 1ed3ec7..9a758e4 100644 (file)
 
 package models
 
-import (
-       "e2mgr/logger"
-)
-
-type NotificationResponse struct {
-
-       MgsType           int
-       RanName       string
-       Payload       []byte
-}
-
-func (response NotificationResponse) GetMessageAsBytes(logger *logger.Logger) []byte {
-       return response.Payload
+type GetNodebRequest struct {
+       RanName string
 }
diff --git a/E2Manager/models/get_nodeb_response.go b/E2Manager/models/get_nodeb_response.go
new file mode 100644 (file)
index 0000000..9c2bd8a
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package models
+
+import (
+       "e2mgr/e2managererrors"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/golang/protobuf/jsonpb"
+)
+
+type GetNodebResponse struct {
+       nodebInfo *entities.NodebInfo
+}
+
+func NewGetNodebResponse(nodebInfo *entities.NodebInfo) *GetNodebResponse {
+       return &GetNodebResponse{
+               nodebInfo: nodebInfo,
+       }
+}
+
+func (response *GetNodebResponse) Marshal() (string, error) {
+       m := jsonpb.Marshaler{}
+       result, err := m.MarshalToString(response.nodebInfo)
+
+       if err != nil {
+               return "", e2managererrors.NewInternalError()
+       }
+
+       return result, nil
+
+}
diff --git a/E2Manager/models/i_response.go b/E2Manager/models/i_response.go
new file mode 100644 (file)
index 0000000..27423ce
--- /dev/null
@@ -0,0 +1,22 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package models
+
+type IResponse interface {
+       Marshal() (string, error)
+}
diff --git a/E2Manager/models/resource_status_payload.go b/E2Manager/models/resource_status_payload.go
new file mode 100644 (file)
index 0000000..69f64cc
--- /dev/null
@@ -0,0 +1,18 @@
+package models
+
+import (
+       "e2mgr/enums"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+)
+
+type ResourceStatusPayload struct {
+       NodeType         entities.Node_Type     `json:"nodeType"`
+       MessageDirection enums.MessageDirection `json:"messageDirection"`
+}
+
+func NewResourceStatusPayload(nodeType entities.Node_Type, messageDirection enums.MessageDirection) *ResourceStatusPayload {
+       return &ResourceStatusPayload{
+               NodeType:         nodeType,
+               MessageDirection: messageDirection,
+       }
+}
diff --git a/E2Manager/models/rmr_message.go b/E2Manager/models/rmr_message.go
new file mode 100644 (file)
index 0000000..ef102c4
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package models
+
+import (
+       "e2mgr/logger"
+)
+
+type RmrMessage struct {
+       MsgType int
+       RanName string
+       Payload []byte
+}
+
+func NewRmrMessage(msgType int, ranName string, payload []byte) *RmrMessage {
+       return &RmrMessage{
+               MsgType: msgType,
+               RanName: ranName,
+               Payload: payload,
+       }
+}
+
+func (response RmrMessage) GetMessageAsBytes(logger *logger.Logger) []byte {
+       return response.Payload
+}
index 23493cd..2d9e3dd 100644 (file)
@@ -13,7 +13,6 @@
 // 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.
-//
 
 package httpmsghandlerprovider
 
@@ -24,16 +23,19 @@ import (
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
 type IncomingRequest string
 
 const (
-       ShutdownRequest  IncomingRequest = "Shutdown"
-       ResetRequest     IncomingRequest = "Reset"
-       X2SetupRequest   IncomingRequest = "X2SetupRequest"
-       EndcSetupRequest IncomingRequest = "EndcSetupRequest"
+       ShutdownRequest       IncomingRequest = "Shutdown"
+       ResetRequest          IncomingRequest = "Reset"
+       X2SetupRequest        IncomingRequest = "X2SetupRequest"
+       EndcSetupRequest      IncomingRequest = "EndcSetupRequest"
+       GetNodebRequest       IncomingRequest = "GetNodebRequest"
+       GetNodebIdListRequest IncomingRequest = "GetNodebIdListRequest"
 )
 
 type IncomingRequestHandlerProvider struct {
@@ -41,21 +43,23 @@ type IncomingRequestHandlerProvider struct {
        logger     *logger.Logger
 }
 
-func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrService *services.RmrService, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager) *IncomingRequestHandlerProvider {
+func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager) *IncomingRequestHandlerProvider {
 
        return &IncomingRequestHandlerProvider{
-               requestMap: initRequestHandlerMap(logger, rmrService, config, rNibDataService, ranSetupManager),
+               requestMap: initRequestHandlerMap(logger, rmrSender, config, rNibDataService, ranSetupManager),
                logger:     logger,
        }
 }
 
-func initRequestHandlerMap(logger *logger.Logger, rmrService *services.RmrService, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager) map[IncomingRequest]httpmsghandlers.RequestHandler {
+func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager) map[IncomingRequest]httpmsghandlers.RequestHandler {
 
        return map[IncomingRequest]httpmsghandlers.RequestHandler{
-               ShutdownRequest: httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrService, config, rNibDataService), //TODO change to pointer
-               ResetRequest:    httpmsghandlers.NewX2ResetRequestHandler(logger, rmrService, rNibDataService),
-               X2SetupRequest:    httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST),
-               EndcSetupRequest:    httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST), //TODO change to pointer
+               ShutdownRequest:  httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService), //TODO change to pointer
+               ResetRequest:     httpmsghandlers.NewX2ResetRequestHandler(logger, rmrSender, rNibDataService),
+               X2SetupRequest:   httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST),
+               EndcSetupRequest: httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST), //TODO change to pointer
+               GetNodebRequest:  httpmsghandlers.NewGetNodebRequestHandler(logger, rNibDataService),
+               GetNodebIdListRequest: httpmsghandlers.NewGetNodebIdListRequestHandler(logger, rNibDataService),
        }
 }
 
index 393b800..4674493 100644 (file)
@@ -24,10 +24,10 @@ import (
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/mocks"
-       "e2mgr/models"
        "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
        "github.com/stretchr/testify/assert"
@@ -35,11 +35,10 @@ import (
        "testing"
 )
 
-func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService {
+func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       messageChannel := make(chan *models.NotificationResponse)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, messageChannel)
+       return rmrsender.NewRmrSender(log, &rmrMessenger)
 }
 
 func setupTest(t *testing.T) *IncomingRequestHandlerProvider {
@@ -53,8 +52,9 @@ func setupTest(t *testing.T) *IncomingRequestHandlerProvider {
                return &mocks.RnibWriterMock{}
        }
        rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
-       ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rnibDataService)
-       return NewIncomingRequestHandlerProvider(log, getRmrService(rmrMessengerMock, log), configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
+       rmrSender := getRmrSender(rmrMessengerMock, log)
+       ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
+       return NewIncomingRequestHandlerProvider(log, rmrSender, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
 }
 
 func TestNewIncomingRequestHandlerProvider(t *testing.T) {
index d85bf95..5f92a8b 100644 (file)
 package rmrmsghandlerprovider
 
 import (
+       "e2mgr/converters"
        "e2mgr/handlers/rmrmsghandlers"
+       "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "fmt"
 )
 
@@ -29,26 +32,25 @@ type NotificationHandlerProvider struct {
        notificationHandlers map[int]rmrmsghandlers.NotificationHandler
 }
 
-func NewNotificationHandlerProvider(rnibDataService services.RNibDataService, ranReconnectionManager *managers.RanReconnectionManager) *NotificationHandlerProvider {
+func NewNotificationHandlerProvider(logger *logger.Logger, rnibDataService services.RNibDataService, ranReconnectionManager *managers.RanReconnectionManager, ranStatusChangeManager *managers.RanStatusChangeManager, rmrSender *rmrsender.RmrSender, x2SetupResponseManager *managers.X2SetupResponseManager, x2SetupFailureResponseManager *managers.X2SetupFailureResponseManager) *NotificationHandlerProvider {
        return &NotificationHandlerProvider{
-               notificationHandlers: initNotificationHandlersMap(rnibDataService, ranReconnectionManager),
+               notificationHandlers: initNotificationHandlersMap(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager),
        }
 }
 
-//TODO change handlers.NotificationHandler to *handlers.NotificationHandler
-func initNotificationHandlersMap(rnibDataService services.RNibDataService, ranReconnectionManager *managers.RanReconnectionManager) map[int]rmrmsghandlers.NotificationHandler {
+func initNotificationHandlersMap(logger *logger.Logger, rnibDataService services.RNibDataService, ranReconnectionManager *managers.RanReconnectionManager, ranStatusChangeManager *managers.RanStatusChangeManager, rmrSender *rmrsender.RmrSender, x2SetupResponseManager *managers.X2SetupResponseManager, x2SetupFailureResponseManager *managers.X2SetupFailureResponseManager) map[int]rmrmsghandlers.NotificationHandler {
        return map[int]rmrmsghandlers.NotificationHandler{
-               rmrCgo.RIC_X2_SETUP_RESP:           rmrmsghandlers.NewSetupResponseNotificationHandler(rnibDataService, managers.NewX2SetupResponseManager(), "X2 Setup Response"),
-               rmrCgo.RIC_X2_SETUP_FAILURE:        rmrmsghandlers.NewSetupResponseNotificationHandler(rnibDataService, managers.NewX2SetupFailureResponseManager(), "X2 Setup Failure Response"),
-               rmrCgo.RIC_ENDC_X2_SETUP_RESP:      rmrmsghandlers.NewSetupResponseNotificationHandler(rnibDataService, managers.NewEndcSetupResponseManager(), "ENDC Setup Response"),
-               rmrCgo.RIC_ENDC_X2_SETUP_FAILURE:   rmrmsghandlers.NewSetupResponseNotificationHandler(rnibDataService, managers.NewEndcSetupFailureResponseManager(), "ENDC Setup Failure Response"),
-               rmrCgo.RIC_SCTP_CONNECTION_FAILURE: rmrmsghandlers.NewRanLostConnectionHandler(ranReconnectionManager),
-               rmrCgo.RIC_ENB_LOAD_INFORMATION:    rmrmsghandlers.NewEnbLoadInformationNotificationHandler(rnibDataService),
-               rmrCgo.RIC_ENB_CONF_UPDATE:         rmrmsghandlers.NewX2EnbConfigurationUpdateHandler(),
-               rmrCgo.RIC_ENDC_CONF_UPDATE:        rmrmsghandlers.NewEndcConfigurationUpdateHandler(),
-               rmrCgo.RIC_X2_RESET_RESP:           rmrmsghandlers.NewX2ResetResponseHandler(rnibDataService),
-               rmrCgo.RIC_X2_RESET:                rmrmsghandlers.NewX2ResetRequestNotificationHandler(rnibDataService),
-               rmrCgo.RIC_E2_TERM_INIT:            rmrmsghandlers.NewE2TermInitNotificationHandler(ranReconnectionManager, rnibDataService),
+               rmrCgo.RIC_X2_SETUP_RESP:           rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP),
+               rmrCgo.RIC_X2_SETUP_FAILURE:        rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, x2SetupFailureResponseManager, nil, rmrCgo.RIC_X2_SETUP_FAILURE),
+               rmrCgo.RIC_ENDC_X2_SETUP_RESP:      rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, managers.NewEndcSetupResponseManager(), ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_RESP),
+               rmrCgo.RIC_ENDC_X2_SETUP_FAILURE:   rmrmsghandlers.NewSetupResponseNotificationHandler(logger, rnibDataService, managers.NewEndcSetupFailureResponseManager(), nil, rmrCgo.RIC_ENDC_X2_SETUP_FAILURE),
+               rmrCgo.RIC_SCTP_CONNECTION_FAILURE: rmrmsghandlers.NewRanLostConnectionHandler(logger, ranReconnectionManager),
+               rmrCgo.RIC_ENB_LOAD_INFORMATION:    rmrmsghandlers.NewEnbLoadInformationNotificationHandler(logger, rnibDataService, converters.NewEnbLoadInformationExtractor(logger)),
+               rmrCgo.RIC_ENB_CONF_UPDATE:         rmrmsghandlers.NewX2EnbConfigurationUpdateHandler(logger, rmrSender),
+               rmrCgo.RIC_ENDC_CONF_UPDATE:        rmrmsghandlers.NewEndcConfigurationUpdateHandler(logger, rmrSender),
+               rmrCgo.RIC_X2_RESET_RESP:           rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(logger)),
+               rmrCgo.RIC_X2_RESET:                rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender),
+               rmrCgo.RIC_E2_TERM_INIT:            rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, rnibDataService),
        }
 }
 
@@ -60,5 +62,4 @@ func (provider NotificationHandlerProvider) GetNotificationHandler(messageType i
        }
 
        return handler, nil
-
 }
index 463259a..1d525ac 100644 (file)
@@ -19,13 +19,14 @@ package rmrmsghandlerprovider
 
 import (
        "e2mgr/configuration"
+       "e2mgr/converters"
        "e2mgr/handlers/rmrmsghandlers"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/mocks"
-       "e2mgr/models"
        "e2mgr/rNibWriter"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
@@ -39,7 +40,7 @@ import (
  * Verify support for known providers.
  */
 
-func initTestCase(t *testing.T) (services.RNibDataService, *managers.RanReconnectionManager) {
+func initTestCase(t *testing.T) (*logger.Logger, services.RNibDataService, *managers.RanReconnectionManager, *managers.RanStatusChangeManager, *rmrsender.RmrSender, *managers.X2SetupResponseManager, *managers.X2SetupFailureResponseManager) {
        logger := initLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
@@ -51,34 +52,47 @@ func initTestCase(t *testing.T) (services.RNibDataService, *managers.RanReconnec
        rnibWriterProvider := func() rNibWriter.RNibWriter {
                return writerMock
        }
+
+       rmrSender := initRmrSender(&mocks.RmrMessengerMock{}, logger)
        rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
-       ranSetupManager := managers.NewRanSetupManager(logger, getRmrService(&mocks.RmrMessengerMock{}, logger), rnibDataService)
+       ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
        ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
-       return rnibDataService, ranReconnectionManager
+       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
+
+       x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
+       x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter)
+
+       x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
+       x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
+
+
+       return logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager
 }
 
 func TestGetNotificationHandlerSuccess(t *testing.T) {
 
-       rnibDataService, ranReconnectionManager := initTestCase(t)
+       logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager := initTestCase(t)
 
        var testCases = []struct {
                msgType int
                handler rmrmsghandlers.NotificationHandler
        }{
-               {rmrCgo.RIC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(rnibDataService, managers.NewX2SetupResponseManager(), "X2 Setup Response")},
-               {rmrCgo.RIC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(rnibDataService, managers.NewX2SetupFailureResponseManager(), "X2 Setup Failure Response")},
-               {rmrCgo.RIC_ENDC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(rnibDataService, managers.NewEndcSetupResponseManager(), "ENDC Setup Response")},
-               {rmrCgo.RIC_ENDC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(rnibDataService, managers.NewEndcSetupFailureResponseManager(), "ENDC Setup Failure Response"),},
-               {rmrCgo.RIC_SCTP_CONNECTION_FAILURE, rmrmsghandlers.NewRanLostConnectionHandler(ranReconnectionManager)},
-               {rmrCgo.RIC_ENB_LOAD_INFORMATION, rmrmsghandlers.NewEnbLoadInformationNotificationHandler(rnibDataService)},
-               {rmrCgo.RIC_ENB_CONF_UPDATE, rmrmsghandlers.X2EnbConfigurationUpdateHandler{}},
-               {rmrCgo.RIC_ENDC_CONF_UPDATE, rmrmsghandlers.EndcConfigurationUpdateHandler{}},
-               {rmrCgo.RIC_E2_TERM_INIT, rmrmsghandlers.NewE2TermInitNotificationHandler(ranReconnectionManager, rnibDataService)},
+               {rmrCgo.RIC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(logger,rnibDataService, x2SetupResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)},
+               {rmrCgo.RIC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(logger,rnibDataService, x2SetupFailureResponseManager, ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_FAILURE)},
+               {rmrCgo.RIC_ENDC_X2_SETUP_RESP, rmrmsghandlers.NewSetupResponseNotificationHandler(logger,rnibDataService, managers.NewEndcSetupResponseManager(), ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_RESP)},
+               {rmrCgo.RIC_ENDC_X2_SETUP_FAILURE, rmrmsghandlers.NewSetupResponseNotificationHandler(logger,rnibDataService, managers.NewEndcSetupFailureResponseManager(), ranStatusChangeManager, rmrCgo.RIC_ENDC_X2_SETUP_FAILURE),},
+               {rmrCgo.RIC_SCTP_CONNECTION_FAILURE, rmrmsghandlers.NewRanLostConnectionHandler(logger,ranReconnectionManager)},
+               {rmrCgo.RIC_ENB_LOAD_INFORMATION, rmrmsghandlers.NewEnbLoadInformationNotificationHandler(logger,rnibDataService, converters.NewEnbLoadInformationExtractor(logger))},
+               {rmrCgo.RIC_ENB_CONF_UPDATE, rmrmsghandlers.NewX2EnbConfigurationUpdateHandler(logger, rmrSender)},
+               {rmrCgo.RIC_ENDC_CONF_UPDATE, rmrmsghandlers.NewEndcConfigurationUpdateHandler(logger, rmrSender)},
+               {rmrCgo.RIC_E2_TERM_INIT, rmrmsghandlers.NewE2TermInitNotificationHandler(logger,ranReconnectionManager, rnibDataService)},
+               {rmrCgo.RIC_X2_RESET_RESP, rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(logger))},
+               {rmrCgo.RIC_X2_RESET, rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger,rnibDataService, ranStatusChangeManager, rmrSender)},
        }
 
        for _, tc := range testCases {
 
-               provider := NewNotificationHandlerProvider(rnibDataService, ranReconnectionManager)
+               provider := NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager)
                t.Run(fmt.Sprintf("%d", tc.msgType), func(t *testing.T) {
                        handler, err := provider.GetNotificationHandler(tc.msgType)
                        if err != nil {
@@ -107,8 +121,8 @@ func TestGetNotificationHandlerFailure(t *testing.T) {
        }
        for _, tc := range testCases {
 
-               rnibDataService, ranReconnectionManager := initTestCase(t)
-               provider := NewNotificationHandlerProvider(rnibDataService, ranReconnectionManager)
+               logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager := initTestCase(t)
+               provider := NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager)
                t.Run(fmt.Sprintf("%d", tc.msgType), func(t *testing.T) {
                        _, err := provider.GetNotificationHandler(tc.msgType)
                        if err == nil {
@@ -122,11 +136,10 @@ func TestGetNotificationHandlerFailure(t *testing.T) {
 }
 
 // TODO: extract to test_utils
-func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService {
+func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       messageChannel := make(chan *models.NotificationResponse)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, messageChannel)
+       return rmrsender.NewRmrSender(log, &rmrMessenger)
 }
 
 // TODO: extract to test_utils
index 4dabf92..0b73b60 100644 (file)
@@ -4,7 +4,7 @@ http:
   port: 3800
 rmr:
   port: 3801
-  maxMsgSize: 4096
+  maxMsgSize: 65536
 notificationResponseBuffer: 100
 bigRedButtonTimeoutSec: 5
 maxConnectionAttempts: 3
index 1bac250..f2ee545 100644 (file)
@@ -54,10 +54,10 @@ func (*Context) Init(port string, maxMsgSize int, flags int, logger *logger.Logg
        return &r
 }
 
-func (ctx *Context) SendMsg(msg *MBuf, maxMsgSize int) (*MBuf, error) {
+func (ctx *Context) SendMsg(msg *MBuf) (*MBuf, error) {
        ctx.checkContextInitialized()
        ctx.Logger.Debugf("#rmrCgoApi.SendMsg - Going to send message. MBuf: %v", *msg)
-       allocatedCMBuf := ctx.getAllocatedCRmrMBuf(ctx.Logger, msg, maxMsgSize)
+       allocatedCMBuf := ctx.getAllocatedCRmrMBuf(ctx.Logger, msg, ctx.MaxMsgSize)
        defer C.rmr_free_msg(allocatedCMBuf)
        state := allocatedCMBuf.state
        if state != RMR_OK {
index 59fd93f..b71b8f1 100644 (file)
@@ -114,7 +114,7 @@ func TestIsReadyFailure(t *testing.T) {
 //     }
 //     msg := NewMBuf(1, tests.MaxMsgSize, &tests.DummyPayload, &tests.DummyXAction)
 //     log.Debugf("#rmrCgoApi_test.TestSendRecvMsgSuccess - Going to send the message: %#v\n", msg)
-//     msgR, _ := (*msgr).SendMsg(msg, tests.MaxMsgSize)
+//     msgR, _ := (*msgr).SendMsg(msg)
 //     log.Debugf("#rmrCgoApi_test.TestSendRecvMsgSuccess - The message has been sent %#v\n", msgR)
 //     log.Debugf("#rmrCgoApi_test.TestSendRecvMsgSuccess - The payload: %#v\n", msgR.Payload)
 //     msgR = (*msgr).RecvMsg()
index 441ed9f..0e351d7 100644 (file)
@@ -68,6 +68,9 @@ const (
        RIC_X2_RESET_RESP                    = C.RIC_X2_RESET_RESP
        RIC_X2_RESET                         = C.RIC_X2_RESET
        RIC_E2_TERM_INIT                                         = C.E2_TERM_INIT
+       RAN_CONNECTED                                            = C.RAN_CONNECTED
+       RAN_RESTARTED                                            = C.RAN_RESTARTED
+       RAN_RECONFIGURED                                         = C.RAN_RECONFIGURED
 )
 
 const (
@@ -133,7 +136,7 @@ type Context struct {
 
 type RmrMessenger interface {
        Init(port string, maxMsgSize int, flags int, logger *logger.Logger) *RmrMessenger
-       SendMsg(msg *MBuf, maxMsgSize int) (*MBuf, error)
+       SendMsg(msg *MBuf) (*MBuf, error)
        RecvMsg() (*MBuf, error)
        RtsMsg(msg *MBuf)
        IsReady() bool
index 20f2f58..db4c6b0 100644 (file)
@@ -16,5 +16,8 @@ rte|10080|10.0.2.15:3801
 rte|10081|10.0.2.15:38000
 rte|10082|10.0.2.15:38000
 rte|1090|10.0.2.15:38000
-
+rte|1200|10.0.2.15:4801
+rte|1210|10.0.2.15:4801
+rte|1220|10.0.2.15:4801
+rte|10090|10.0.2.15:38000
 newrt|end
diff --git a/E2Manager/services/receivers/rmr_service_receiver.go b/E2Manager/services/receivers/rmr_service_receiver.go
deleted file mode 100644 (file)
index 7ffceb4..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// 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.
-//
-
-package receivers
-
-import (
-       "e2mgr/managers/notificationmanager"
-       "e2mgr/services"
-)
-
-// RmrService holds an instance of RMR messenger as well as its configuration
-type RmrServiceReceiver struct {
-       services.RmrService
-       nManager *notificationmanager.NotificationManager
-}
-
-// NewRmrService instantiates a new Rmr service instance
-func NewRmrServiceReceiver(rmrService services.RmrService, nManager *notificationmanager.NotificationManager) *RmrServiceReceiver {
-
-       return &RmrServiceReceiver{
-               RmrService: rmrService,
-               nManager:   nManager,
-       }
-}
-
-// ListenAndHandle waits for messages coming from rmr_rcv_msg and sends it to a designated message handler
-func (r *RmrServiceReceiver) ListenAndHandle() {
-
-       for {
-               mbuf, err := (*r.Messenger).RecvMsg()
-               r.Config.Logger.Debugf("#rmr_service_receiver.ListenAndHandle - Going to handle received message: %#v\n", mbuf)
-
-               // TODO: one mbuf received immediately execute goroutine
-               if err != nil {
-                       continue //TODO log error
-               }
-
-               r.nManager.HandleMessage(r.Config.Logger, mbuf, r.RmrResponse)
-       }
-}
diff --git a/E2Manager/services/rmr_service.go b/E2Manager/services/rmr_service.go
deleted file mode 100644 (file)
index 860f5da..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// 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.
-//
-
-package services
-
-import (
-       "e2mgr/logger"
-       "e2mgr/models"
-       "e2mgr/rmrCgo"
-       "strconv"
-       "sync"
-)
-
-type RmrConfig struct {
-       Port       int
-       MaxMsgSize int
-       Flags      int
-       Logger     *logger.Logger
-}
-
-func NewRmrConfig(port int, maxMsgSize int, flags int, logger *logger.Logger) *RmrConfig {
-       return &RmrConfig{port, maxMsgSize, flags, logger}
-}
-
-// RmrService holds an instance of RMR messenger as well as its configuration
-type RmrService struct {
-       Config      *RmrConfig
-       Messenger   *rmrCgo.RmrMessenger
-       RmrResponse chan *models.NotificationResponse
-}
-
-// NewRmrService instantiates a new Rmr service instance
-func NewRmrService(rmrConfig *RmrConfig, msrImpl rmrCgo.RmrMessenger, rmrResponse chan *models.NotificationResponse) *RmrService {
-
-       return &RmrService{
-               Config:      rmrConfig,
-               Messenger:   msrImpl.Init("tcp:"+strconv.Itoa(rmrConfig.Port), rmrConfig.MaxMsgSize, rmrConfig.Flags, rmrConfig.Logger),
-               RmrResponse: rmrResponse,
-       }
-}
-
-func (r *RmrService) SendMessage(messageType int, messageChannel chan *models.E2RequestMessage, errorChannel chan error,
-       wg sync.WaitGroup) {
-
-       wg.Add(1)
-       setupRequestMessage := <-messageChannel
-       e2Message := setupRequestMessage.GetMessageAsBytes(r.Config.Logger)
-
-       transactionId := []byte(setupRequestMessage.TransactionId())
-
-       msg := rmrCgo.NewMBuf(messageType, len(e2Message) /*r.config.MaxMsgSize*/, setupRequestMessage.RanName(), &e2Message, &transactionId)
-
-       r.Config.Logger.Debugf("#rmr_service.SendMessage - Going to send the message: %#v\n", msg)
-       _, err := (*r.Messenger).SendMsg(msg, r.Config.MaxMsgSize)
-
-       errorChannel <- err
-       wg.Done()
-}
-
-func (r *RmrService) SendRmrMessage(response *models.NotificationResponse) error {
-
-       msgAsBytes := response.GetMessageAsBytes(r.Config.Logger)
-       transactionIdByteArr := []byte(response.RanName)
-
-       msg := rmrCgo.NewMBuf(response.MgsType, len(msgAsBytes), response.RanName, &msgAsBytes, &transactionIdByteArr)
-
-       _, err := (*r.Messenger).SendMsg(msg, r.Config.MaxMsgSize)
-
-       if err != nil {
-               return err
-       }
-       return nil
-}
-
-func (r *RmrService) SendResponse() {
-       for {
-
-               response, ok := <-r.RmrResponse
-               if !ok {
-
-                       r.Config.Logger.Errorf("#rmr_service.SendResponse - channel closed")
-                       break
-               }
-
-               r.Config.Logger.Debugf("#rmr_service.SendResponse - Going to send message: %#v\n", response)
-               if err := r.SendRmrMessage(response); err != nil {
-                       r.Config.Logger.Errorf("#rmr_service.SendResponse - error: %#v\n", err)
-               }
-       }
-}
-
-func (r *RmrService) CloseContext() {
-       if r.Config.Logger.DebugEnabled() {
-               r.Config.Logger.Debugf("#rmr_service.CloseContext - RMR is ready: %v", (*r.Messenger).IsReady())
-               (*r.Messenger).Close()
-               r.Config.Logger.Debugf("#rmr_service.CloseContext - RMR is ready: %v", (*r.Messenger).IsReady())
-       }
-}
diff --git a/E2Manager/services/rmr_service_test.go b/E2Manager/services/rmr_service_test.go
deleted file mode 100644 (file)
index b4165db..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 2019 Nokia
-//
-// 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.
-//
-
-package services
-
-import (
-       "e2mgr/logger"
-       "e2mgr/mocks"
-       "e2mgr/models"
-       "e2mgr/rmrCgo"
-       "e2mgr/tests"
-       "fmt"
-       "github.com/stretchr/testify/assert"
-       "github.com/stretchr/testify/mock"
-       "sync"
-       "testing"
-       "time"
-)
-
-func TestNewRmrConfig(t *testing.T) {
-       log, err := logger.InitLogger(logger.InfoLevel)
-       if err != nil {
-               t.Errorf("#rmr_service_test.TestNewRmrConfig - failed to initialize logger, error: %s", err)
-       }
-       assert.NotNil(t, NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log))
-}
-
-func TestSendMessage(t *testing.T){
-       log, err := logger.InitLogger(logger.DebugLevel)
-       if err!=nil{
-               t.Errorf("#rmr_service_test.TestSendMessage - failed to initialize logger, error: %s", err)
-       }
-       rmrMessengerMock := &mocks.RmrMessengerMock{}
-       mbuf := rmrCgo.NewMBuf(tests.MessageType, tests.MaxMsgSize,"RanName" , &tests.DummyPayload, &tests.DummyXAction)
-       rmrMessengerMock.On("SendMsg", mock.AnythingOfType(fmt.Sprintf("%T", mbuf)), tests.MaxMsgSize).Return(mbuf, nil)
-
-       errorChannel := make(chan error)
-       var wg sync.WaitGroup
-       go getRmrService( rmrMessengerMock, log).SendMessage(tests.MessageType, make(chan *models.E2RequestMessage), errorChannel, wg)
-       wg.Wait()
-
-       assert.Empty (t, errorChannel)
-}
-
-func TestCloseContext(t *testing.T){
-       log, err := logger.InitLogger(logger.DebugLevel)
-       if err!=nil{
-               t.Errorf("#rmr_service_test.TestCloseContext - failed to initialize logger, error: %s", err)
-       }
-       rmrMessengerMock := &mocks.RmrMessengerMock{}
-
-       rmrMessengerMock.On("IsReady").Return(true)
-       rmrMessengerMock.On("Close").Return()
-
-       getRmrService(rmrMessengerMock, log).CloseContext()
-       time.Sleep(time.Microsecond*10)
-}
-
-func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *RmrService {
-       rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       messageChannel := make(chan *models.NotificationResponse)
-       rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return NewRmrService(NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger,  messageChannel)
-}
diff --git a/E2Manager/services/rmrreceiver/rmr_receiver.go b/E2Manager/services/rmrreceiver/rmr_receiver.go
new file mode 100644 (file)
index 0000000..8cc807f
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package rmrreceiver
+
+import (
+       "e2mgr/logger"
+       "e2mgr/managers/notificationmanager"
+       "e2mgr/rmrCgo"
+)
+
+type RmrReceiver struct {
+       logger    *logger.Logger
+       nManager  *notificationmanager.NotificationManager
+       messenger *rmrCgo.RmrMessenger
+}
+
+func NewRmrReceiver(logger *logger.Logger, messenger *rmrCgo.RmrMessenger, nManager *notificationmanager.NotificationManager) *RmrReceiver {
+       return &RmrReceiver{
+               logger:    logger,
+               nManager:  nManager,
+               messenger: messenger,
+       }
+}
+
+func (r *RmrReceiver) ListenAndHandle() {
+
+       for {
+               mbuf, err := (*r.messenger).RecvMsg()
+               r.logger.Debugf("#RmrReceiver.ListenAndHandle - Going to handle received message: %#v\n", mbuf)
+
+               if err != nil {
+                       // TODO: error handling?
+                       continue
+               }
+
+               // TODO: go routine?
+               _ = r.nManager.HandleMessage(mbuf)
+       }
+}
\ No newline at end of file
 // limitations under the License.
 //
 
-package receivers
+package rmrreceiver
 
 import (
        "e2mgr/configuration"
+       "e2mgr/converters"
        "e2mgr/logger"
        "e2mgr/managers"
        "e2mgr/managers/notificationmanager"
        "e2mgr/mocks"
-       "e2mgr/models"
+       "e2mgr/providers/rmrmsghandlerprovider"
        "e2mgr/rNibWriter"
        "e2mgr/rmrCgo"
        "e2mgr/services"
+       "e2mgr/services/rmrsender"
        "e2mgr/tests"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
@@ -39,25 +41,24 @@ func TestListenAndHandle(t *testing.T) {
        if err != nil {
                t.Errorf("#rmr_service_test.TestListenAndHandle - failed to initialize logger, error: %s", err)
        }
-       rmrMessengerMock := &mocks.RmrMessengerMock{}
-
-       var buf *rmrCgo.MBuf
-       e := fmt.Errorf("test error")
-       rmrMessengerMock.On("RecvMsg").Return(buf, e)
-
-       go getRmrServiceReceiver(rmrMessengerMock, log).ListenAndHandle()
-
+       rmrReceiver := initRmrReceiver(log)
+       go rmrReceiver.ListenAndHandle()
        time.Sleep(time.Microsecond * 10)
 }
 
-func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService {
+func initRmrMessenger(log *logger.Logger) *rmrCgo.RmrMessenger {
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
        rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
-       messageChannel := make(chan *models.NotificationResponse)
        rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
-       return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, messageChannel)
+
+       // TODO: that's not good since we don't actually test anything. if the error is populated then the loop will just continue and it's sort of a "workaround" for that method to be called
+       var buf *rmrCgo.MBuf
+       e := fmt.Errorf("test error")
+       rmrMessengerMock.On("RecvMsg").Return(buf, e)
+       return &rmrMessenger
 }
 
-func getRmrServiceReceiver(rmrMessengerMock *mocks.RmrMessengerMock, logger *logger.Logger) *RmrServiceReceiver {
+func initRmrReceiver(logger *logger.Logger) *RmrReceiver {
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
 
        readerMock := &mocks.RnibReaderMock{}
@@ -70,10 +71,16 @@ func getRmrServiceReceiver(rmrMessengerMock *mocks.RmrMessengerMock, logger *log
        }
 
        rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
-       rmrService := getRmrService(rmrMessengerMock, logger)
-       ranSetupManager := managers.NewRanSetupManager(logger, rmrService, rnibDataService)
+       rmrMessenger := initRmrMessenger(logger)
+       rmrSender := rmrsender.NewRmrSender(logger, rmrMessenger)
+       ranSetupManager := managers.NewRanSetupManager(logger, rmrSender, rnibDataService)
        ranReconnectionManager := managers.NewRanReconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, ranSetupManager)
-       nManager := notificationmanager.NewNotificationManager(rnibDataService, ranReconnectionManager)
-
-       return NewRmrServiceReceiver(*rmrService, nManager)
+       ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
+       x2SetupResponseConverter := converters.NewX2SetupResponseConverter(logger)
+       x2SetupResponseManager := managers.NewX2SetupResponseManager(x2SetupResponseConverter)
+       x2SetupFailureResponseConverter := converters.NewX2SetupFailureResponseConverter(logger)
+       x2SetupFailureResponseManager := managers.NewX2SetupFailureResponseManager(x2SetupFailureResponseConverter)
+       rmrNotificationHandlerProvider := rmrmsghandlerprovider.NewNotificationHandlerProvider(logger, rnibDataService, ranReconnectionManager, ranStatusChangeManager, rmrSender, x2SetupResponseManager, x2SetupFailureResponseManager )
+       notificationManager := notificationmanager.NewNotificationManager(logger, rmrNotificationHandlerProvider)
+       return NewRmrReceiver(logger, rmrMessenger, notificationManager)
 }
diff --git a/E2Manager/services/rmrsender/rmr_sender.go b/E2Manager/services/rmrsender/rmr_sender.go
new file mode 100644 (file)
index 0000000..daf7679
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package rmrsender
+
+import (
+       "e2mgr/logger"
+       "e2mgr/models"
+       "e2mgr/rmrCgo"
+)
+
+type RmrSender struct {
+       logger    *logger.Logger
+       messenger *rmrCgo.RmrMessenger
+}
+
+func NewRmrSender(logger *logger.Logger, messenger *rmrCgo.RmrMessenger) *RmrSender {
+       return &RmrSender{
+               logger:    logger,
+               messenger: messenger,
+       }
+}
+
+func (r *RmrSender) Send(rmrMessage *models.RmrMessage) error {
+       transactionIdByteArr := []byte(rmrMessage.RanName)
+       msg := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &transactionIdByteArr)
+
+       _, err := (*r.messenger).SendMsg(msg)
+
+       if err != nil {
+               r.logger.Errorf("#RmrSender.Send - RAN name: %s , Message type: %d - Failed sending message. Error: %v", rmrMessage.RanName, rmrMessage.MsgType, err)
+               return err
+       }
+
+       r.logger.Infof("#RmrSender.Send - RAN name: %s , Message type: %d - Successfully sent RMR message", rmrMessage.RanName, rmrMessage.MsgType)
+       return nil
+}
diff --git a/E2Manager/services/rmrsender/rmr_sender_test.go b/E2Manager/services/rmrsender/rmr_sender_test.go
new file mode 100644 (file)
index 0000000..26ab0b4
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package rmrsender
+
+import (
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "e2mgr/models"
+       "e2mgr/rmrCgo"
+       "fmt"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func initRmrSenderTest(t *testing.T) (*logger.Logger, *mocks.RmrMessengerMock) {
+       log := initLog(t)
+       rmrMessengerMock := &mocks.RmrMessengerMock{}
+       rmrMessengerMock.On("IsReady").Return(true)
+       rmrMessengerMock.On("Close").Return()
+       return log, rmrMessengerMock
+}
+
+//func TestRmrSender_CloseContext(t *testing.T) {
+//     logger, rmrMessengerMock := initRmrSenderTest(t)
+//
+//     rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
+//     rmrSender := NewRmrSender(logger, &rmrMessenger)
+//
+//     rmrSender.CloseContext()
+//     time.Sleep(time.Microsecond * 10)
+//}
+
+func TestRmrSenderSendSuccess(t *testing.T) {
+       logger, rmrMessengerMock := initRmrSenderTest(t)
+
+       ranName := "test"
+       payload := []byte("some payload")
+       xaction := []byte(ranName)
+       mbuf := rmrCgo.NewMBuf(123, len(payload), ranName, &payload, &xaction)
+       rmrMessengerMock.On("SendMsg", mbuf).Return(&rmrCgo.MBuf{}, nil)
+       rmrMsg := models.NewRmrMessage(123, ranName, payload)
+       rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
+       rmrSender := NewRmrSender(logger, &rmrMessenger)
+       err := rmrSender.Send(rmrMsg)
+       assert.Nil(t, err)
+       rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf)
+
+}
+
+func TestRmrSenderSendFailure(t *testing.T) {
+       logger, rmrMessengerMock := initRmrSenderTest(t)
+
+       ranName := "test"
+       payload := []byte("some payload")
+       xaction := []byte(ranName)
+       mbuf := rmrCgo.NewMBuf(123, len(payload), ranName, &payload, &xaction)
+       rmrMessengerMock.On("SendMsg", mbuf).Return(mbuf, fmt.Errorf("rmr send failure"))
+       rmrMsg := models.NewRmrMessage(123, ranName, payload)
+       rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
+       rmrSender := NewRmrSender(logger, &rmrMessenger)
+       err := rmrSender.Send(rmrMsg)
+       rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf)
+       assert.NotNil(t, err)
+}
+
+// TODO: extract to test_utils
+func initLog(t *testing.T) *logger.Logger {
+       log, err := logger.InitLogger(logger.InfoLevel)
+       if err != nil {
+               t.Fatalf("#initLog - failed to initialize logger, error: %s", err)
+       }
+       return log
+}
index 8a91894..02f8e1d 100644 (file)
@@ -1,12 +1,29 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
 package services
 
 import (
        "e2mgr/configuration"
        "e2mgr/logger"
        "e2mgr/rNibWriter"
-       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "net"
        "time"
 )
@@ -17,6 +34,7 @@ type RNibDataService interface {
        SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error
        GetNodeb(ranName string) (*entities.NodebInfo, error)
        GetListNodebIds() ([]*entities.NbIdentity, error)
+       PingRnib() bool
 }
 
 type rNibDataService struct {
@@ -71,7 +89,7 @@ func (w *rNibDataService) SaveRanLoadInformation(inventoryName string, ranLoadIn
 }
 
 func (w *rNibDataService) GetNodeb(ranName string) (*entities.NodebInfo, error) {
-       w.logger.Infof("#RnibDataService.GetNodeb - ranName: %s", ranName)
+       w.logger.Infof("#RnibDataService.GetNodeb - RAN name: %s", ranName)
 
        var nodeb *entities.NodebInfo = nil
 
@@ -96,6 +114,15 @@ func (w *rNibDataService) GetListNodebIds() ([]*entities.NbIdentity, error) {
        return nodeIds, err
 }
 
+func (w *rNibDataService) PingRnib() bool {
+       err := w.retry("GetListNodebIds", func() (err error) {
+               _, err = w.rnibReaderProvider().GetListNodebIds()
+               return
+       })
+
+       return !isRnibConnectionError(err)
+}
+
 func (w *rNibDataService) retry(rnibFunc string, f func() error) (err error) {
        attempts := w.maxAttempts
 
@@ -104,7 +131,7 @@ func (w *rNibDataService) retry(rnibFunc string, f func() error) (err error) {
                if err == nil {
                        return
                }
-               if !w.isConnError(err) {
+               if !isRnibConnectionError(err) {
                        return err
                }
                if i >= attempts {
@@ -117,8 +144,9 @@ func (w *rNibDataService) retry(rnibFunc string, f func() error) (err error) {
        }
 }
 
-func (w *rNibDataService) isConnError(err error) bool {
-       internalErr, ok := err.(common.InternalError)
+
+func isRnibConnectionError(err error) bool {
+       internalErr, ok := err.(*common.InternalError)
        if !ok {
                return false
        }
index 7a96310..8d57b4e 100644 (file)
@@ -1,3 +1,20 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
 package services
 
 import (
@@ -15,13 +32,17 @@ import (
        "testing"
 )
 
-func setupTest(t *testing.T) (*rNibDataService, *mocks.RnibReaderMock, *mocks.RnibWriterMock) {
+func setupRnibDataServiceTest(t *testing.T) (*rNibDataService, *mocks.RnibReaderMock, *mocks.RnibWriterMock) {
+       return setupRnibDataServiceTestWithMaxAttempts(t, 3)
+}
+
+func setupRnibDataServiceTestWithMaxAttempts(t *testing.T, maxAttempts int) (*rNibDataService, *mocks.RnibReaderMock, *mocks.RnibWriterMock) {
        logger, err := logger.InitLogger(logger.DebugLevel)
        if err != nil {
                t.Errorf("#... - failed to initialize logger, error: %s", err)
        }
 
-       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: maxAttempts}
 
        readerMock := &mocks.RnibReaderMock{}
        rnibReaderProvider := func() reader.RNibReader {
@@ -40,7 +61,7 @@ func setupTest(t *testing.T) (*rNibDataService, *mocks.RnibReaderMock, *mocks.Rn
 }
 
 func TestSuccessfulSaveNodeb(t *testing.T) {
-       rnibDataService, _, writerMock := setupTest(t)
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
 
        nodebInfo := &entities.NodebInfo{}
        nbIdentity := &entities.NbIdentity{}
@@ -51,11 +72,11 @@ func TestSuccessfulSaveNodeb(t *testing.T) {
 }
 
 func TestConnFailureSaveNodeb(t *testing.T) {
-       rnibDataService, _, writerMock := setupTest(t)
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
 
        nodebInfo := &entities.NodebInfo{}
        nbIdentity := &entities.NbIdentity{}
-       mockErr := common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
        writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(mockErr)
 
        rnibDataService.SaveNodeb(nbIdentity, nodebInfo)
@@ -63,11 +84,11 @@ func TestConnFailureSaveNodeb(t *testing.T) {
 }
 
 func TestNonConnFailureSaveNodeb(t *testing.T) {
-       rnibDataService, _, writerMock := setupTest(t)
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
 
        nodebInfo := &entities.NodebInfo{}
        nbIdentity := &entities.NbIdentity{}
-       mockErr := common.InternalError{Err: fmt.Errorf("non connection failure")}
+       mockErr := &common.InternalError{Err: fmt.Errorf("non connection failure")}
        writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(mockErr)
 
        rnibDataService.SaveNodeb(nbIdentity, nodebInfo)
@@ -75,7 +96,7 @@ func TestNonConnFailureSaveNodeb(t *testing.T) {
 }
 
 func TestSuccessfulUpdateNodebInfo(t *testing.T) {
-       rnibDataService, _, writerMock := setupTest(t)
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
 
        nodebInfo := &entities.NodebInfo{}
        writerMock.On("UpdateNodebInfo", nodebInfo).Return(nil)
@@ -85,10 +106,10 @@ func TestSuccessfulUpdateNodebInfo(t *testing.T) {
 }
 
 func TestConnFailureUpdateNodebInfo(t *testing.T) {
-       rnibDataService, _, writerMock := setupTest(t)
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
 
        nodebInfo := &entities.NodebInfo{}
-       mockErr := common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
        writerMock.On("UpdateNodebInfo", nodebInfo).Return(mockErr)
 
        rnibDataService.UpdateNodebInfo(nodebInfo)
@@ -96,7 +117,7 @@ func TestConnFailureUpdateNodebInfo(t *testing.T) {
 }
 
 func TestSuccessfulSaveRanLoadInformation(t *testing.T) {
-       rnibDataService, _, writerMock := setupTest(t)
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
 
        var ranName string = "abcd"
        ranLoadInformation := &entities.RanLoadInformation{}
@@ -107,11 +128,11 @@ func TestSuccessfulSaveRanLoadInformation(t *testing.T) {
 }
 
 func TestConnFailureSaveRanLoadInformation(t *testing.T) {
-       rnibDataService, _, writerMock := setupTest(t)
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
 
        var ranName string = "abcd"
        ranLoadInformation := &entities.RanLoadInformation{}
-       mockErr := common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
        writerMock.On("SaveRanLoadInformation", ranName, ranLoadInformation).Return(mockErr)
 
        rnibDataService.SaveRanLoadInformation(ranName, ranLoadInformation)
@@ -119,7 +140,7 @@ func TestConnFailureSaveRanLoadInformation(t *testing.T) {
 }
 
 func TestSuccessfulGetNodeb(t *testing.T) {
-       rnibDataService, readerMock, _ := setupTest(t)
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
 
        invName := "abcd"
        nodebInfo := &entities.NodebInfo{}
@@ -132,11 +153,11 @@ func TestSuccessfulGetNodeb(t *testing.T) {
 }
 
 func TestConnFailureGetNodeb(t *testing.T) {
-       rnibDataService, readerMock, _ := setupTest(t)
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
 
        invName := "abcd"
        var nodeb *entities.NodebInfo = nil
-       mockErr := common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
        readerMock.On("GetNodeb", invName).Return(nodeb, mockErr)
 
        res, err := rnibDataService.GetNodeb(invName)
@@ -146,7 +167,7 @@ func TestConnFailureGetNodeb(t *testing.T) {
 }
 
 func TestSuccessfulGetNodebIdList(t *testing.T) {
-       rnibDataService, readerMock, _ := setupTest(t)
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
 
        nodeIds := []*entities.NbIdentity{}
        readerMock.On("GetListNodebIds").Return(nodeIds, nil)
@@ -158,10 +179,10 @@ func TestSuccessfulGetNodebIdList(t *testing.T) {
 }
 
 func TestConnFailureGetNodebIdList(t *testing.T) {
-       rnibDataService, readerMock, _ := setupTest(t)
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
 
        var nodeIds []*entities.NbIdentity = nil
-       mockErr := common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
        readerMock.On("GetListNodebIds").Return(nodeIds, mockErr)
 
        res, err := rnibDataService.GetListNodebIds()
@@ -170,12 +191,81 @@ func TestConnFailureGetNodebIdList(t *testing.T) {
        assert.Equal(t, nodeIds, res)
 }
 
+func TestConnFailureTwiceGetNodebIdList(t *testing.T) {
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
+
+       invName := "abcd"
+       var nodeb *entities.NodebInfo = nil
+       var nodeIds []*entities.NbIdentity = nil
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       readerMock.On("GetNodeb", invName).Return(nodeb, mockErr)
+       readerMock.On("GetListNodebIds").Return(nodeIds, mockErr)
+
+       res, err := rnibDataService.GetListNodebIds()
+       readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 3)
+       assert.True(t, strings.Contains(err.Error(), "connection error", ))
+       assert.Equal(t, nodeIds, res)
+
+       res2, err := rnibDataService.GetNodeb(invName)
+       readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
+       assert.True(t, strings.Contains(err.Error(), "connection error", ))
+       assert.Equal(t, nodeb, res2)
+}
+
+func TestConnFailureWithAnotherConfig(t *testing.T) {
+       rnibDataService, readerMock, _ := setupRnibDataServiceTestWithMaxAttempts(t, 5)
+
+       var nodeIds []*entities.NbIdentity = nil
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       readerMock.On("GetListNodebIds").Return(nodeIds, mockErr)
+
+       res, err := rnibDataService.GetListNodebIds()
+       readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 5)
+       assert.True(t, strings.Contains(err.Error(), "connection error", ))
+       assert.Equal(t, nodeIds, res)
+}
+
+func TestPingRnibConnFailure(t *testing.T) {
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
+
+       var nodeIds []*entities.NbIdentity = nil
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       readerMock.On("GetListNodebIds").Return(nodeIds, mockErr)
+
+       res := rnibDataService.PingRnib()
+       readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 3)
+       assert.False(t, res)
+}
+
+func TestPingRnibOkNoError(t *testing.T) {
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
+
+       var nodeIds []*entities.NbIdentity = nil
+       readerMock.On("GetListNodebIds").Return(nodeIds, nil)
+
+       res := rnibDataService.PingRnib()
+       readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 1)
+       assert.True(t, res)
+}
+
+func TestPingRnibOkOtherError(t *testing.T) {
+       rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
+
+       var nodeIds []*entities.NbIdentity = nil
+       mockErr := &common.InternalError{Err: fmt.Errorf("non connection error")}
+       readerMock.On("GetListNodebIds").Return(nodeIds, mockErr)
+
+       res := rnibDataService.PingRnib()
+       readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 1)
+       assert.True(t, res)
+}
+
 //func TestConnFailureThenSuccessGetNodebIdList(t *testing.T) {
-//     rnibDataService, readerMock, _ := setupTest(t)
+//     rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
 //
 //     var nilNodeIds []*entities.NbIdentity = nil
 //     nodeIds := []*entities.NbIdentity{}
-//     mockErr := common.InternalError{Err: &net.OpError{Err:fmt.Errorf("connection error")}}
+//     mockErr := &common.InternalError{Err: &net.OpError{Err:fmt.Errorf("connection error")}}
 //     //readerMock.On("GetListNodebIds").Return(nilNodeIds, mockErr)
 //     //readerMock.On("GetListNodebIds").Return(nodeIds, nil)
 //
diff --git a/E2Manager/stateMachine/delete_all_node_state_machine_test.go b/E2Manager/stateMachine/delete_all_node_state_machine_test.go
new file mode 100644 (file)
index 0000000..629ab65
--- /dev/null
@@ -0,0 +1,14 @@
+package stateMachine
+
+import (
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func TestNodeNextStateDeleteAll(t *testing.T) {
+
+       _, result := NodeNextStateDeleteAll(entities.ConnectionStatus_UNKNOWN_CONNECTION_STATUS)
+
+       assert.False(t, result)
+}
diff --git a/E2Manager/utils/time_utils.go b/E2Manager/utils/time_utils.go
new file mode 100644 (file)
index 0000000..c34730c
--- /dev/null
@@ -0,0 +1,7 @@
+package utils
+
+import "time"
+
+func ElapsedTime(startTime time.Time) float64 {
+       return float64(time.Since(startTime)) / float64(time.Millisecond)
+}
diff --git a/Swagger/E2Manager_API.yaml b/Swagger/E2Manager_API.yaml
new file mode 100644 (file)
index 0000000..685ac2d
--- /dev/null
@@ -0,0 +1,921 @@
+# ========================LICENSE_START=================================
+# O-RAN-SC
+#
+# Copyright (C) 2019 AT&T Intellectual Property and Nokia
+#
+# 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===================================
+
+openapi: 3.0.0
+info:
+  title: E2 Manager Service
+  description: E2 Manager Service APIs
+  version: 2.0.5
+servers:
+  - url: 'http://{apiRoot}/v1'
+    variables:
+      apiRoot:
+        default: 'localhost:3800'
+paths:
+  /nodeb/x2-setup:
+    post:
+      summary: X2 Setup
+      tags:
+        - nodeb
+      operationId: x2Setup
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/SetupRequest'
+        required: true
+      responses:
+        '200':
+          description: Success
+        '400':
+          description: Invalid input
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        '500':
+          description: Internal error
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  /nodeb/endc-setup:
+    post:
+      tags:
+        - nodeb
+      summary: ENDC Setup
+      operationId: endcSetup
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/SetupRequest'
+        required: true
+      responses:
+        '200':
+          description: Success
+        '400':
+          description: Invalid input
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        '500':
+          description: Internal Error
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  '/nodeb/{ranName}':
+    get:
+      tags:
+        - nodeb
+      summary: Get RAN by name
+      operationId: getNb
+      parameters:
+        - name: ranName
+          in: path
+          required: true
+          description: Name of RAN to return
+          schema:
+            type: string
+      responses:
+        '200':
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/GetNodebResponse'
+        '400':
+          description: The specified RAN name is invalid
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        '404':
+          description: A RAN with the specified name was not found
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        '500':
+          description: Internal Error
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  /nodeb/shutdown:
+    put:
+      tags:
+        - nodeb
+      summary: >-
+        Close all connections to the RANs
+      responses:
+        '204':
+          description: Successful operation
+        '500':
+          description: Internal Error
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  /nodeb/ids:
+    get:
+      tags:
+        - nodeb
+      summary: Get RANs identities list
+      operationId: getNodebIdList
+      responses:
+        '200':
+          description: Successful operation
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/NodebIdentity'
+        '500':
+          description: Internal Error
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  /nodeb/{ranName}/reset:
+    put:
+      tags:
+        - nodeb
+      summary: >-
+        Upon receipt of this message, 'ranName' shall abort any other ongoing procedures over X2 between the RIC and the RAN. The RAN shall delete all the context information related to the RIC, except the application level configuration data exchanged during the X2 Setup or eNB Configuration Update procedures, and release the corresponding resource.  
+      operationId: reset
+      parameters:
+        - name: ranName
+          in: path
+          required: true
+          description: Name of RAN to return
+          schema:
+            type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/ResetRequest'
+        required: false
+      responses:
+        '204':
+          description: Successful operation
+        '400':
+          description: Invalid input (invalid cause, RAN in wrong state)
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        '404':
+          description: A RAN with the specified name was not found
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+        '500':
+          description: Internal Error
+          content:
+            application/problem+json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+
+  /health:
+    get:
+      tags:
+        - Health Check
+      summary: E2 Manager Service Health Check
+      responses:
+        '200':
+          description: OK
+components:
+  schemas:
+    SetupRequest:
+      type: object
+      required:
+        - ranIp
+        - ranPort
+        - ranName
+      properties:
+        ranIp:
+          type: string
+        ranPort:
+          type: integer
+          format: uint16
+        ranName:
+          type: string
+    ResetRequest:
+      type: object
+      required:
+        - cause
+      properties:
+        cause:
+          type: string
+          enum: [misc:control-processing-overload,
+misc:hardware-failure,
+misc:om-intervention,
+misc:not-enough-user-plane-processing-resources,
+misc:unspecified,
+protocol:transfer-syntax-error,
+protocol:abstract-syntax-error-reject,
+protocol:abstract-syntax-error-ignore-and-notify,
+protocol:message-not-compatible-with-receiver-state,
+protocol:semantic-error,
+protocol:unspecified,
+protocol:abstract-syntax-error-falsely-constructed-message,
+transport:transport-resource-unavailable,
+transport:unspecified,
+radioNetwork:handover-desirable-for-radio-reasons,
+radioNetwork:time-critical-handover,
+radioNetwork:resource-optimisation-handover,
+radioNetwork:reduce-load-in-serving-cell,
+radioNetwork:partial-handover,
+radioNetwork:unknown-new-eNB-UE-X2AP-ID, 
+radioNetwork:unknown-old-eNB-UE-X2AP-ID, 
+radioNetwork:unknown-pair-of-UE-X2AP-ID,
+radioNetwork:ho-target-not-allowed,
+radioNetwork:tx2relocoverall-expiry,
+radioNetwork:trelocprep-expiry,
+radioNetwork:cell-not-available,
+radioNetwork:no-radio-resources-available-in-target-cell,
+radioNetwork:invalid-MME-GroupID,
+radioNetwork:unknown-MME-Code,
+radioNetwork:encryption-and-or-integrity-protection-algorithms-not-supported,
+radioNetwork:reportCharacteristicsEmpty,
+radioNetwork:noReportPeriodicity,
+radioNetwork:existingMeasurementID,
+radioNetwork:unknown-eNB-Measurement-ID,
+radioNetwork:measurement-temporarily-not-available,
+radioNetwork:unspecified,
+radioNetwork:load-balancing,
+radioNetwork:handover-optimisation,
+radioNetwork:value-out-of-allowed-range,
+radioNetwork:multiple-E-RAB-ID-instances,
+radioNetwork:switch-off-ongoing,
+radioNetwork:not-supported-QCI-value,
+radioNetwork:measurement-not-supported-for-the-object,
+radioNetwork:tDCoverall-expiry,
+radioNetwork:tDCprep-expiry,
+radioNetwork:action-desirable-for-radio-reasons,
+radioNetwork:reduce-load,
+radioNetwork:resource-optimisation,
+radioNetwork:time-critical-action,
+radioNetwork:target-not-allowed,
+radioNetwork:no-radio-resources-available,
+radioNetwork:invalid-QoS-combination,
+radioNetwork:encryption-algorithms-not-aupported,
+radioNetwork:procedure-cancelled,
+radioNetwork:rRM-purpose,
+radioNetwork:improve-user-bit-rate,
+radioNetwork:user-inactivity,
+radioNetwork:radio-connection-with-UE-lost,
+radioNetwork:failure-in-the-radio-interface-procedure,
+radioNetwork:bearer-option-not-supported,
+radioNetwork:mCG-Mobility,
+radioNetwork:sCG-Mobility,
+radioNetwork:count-reaches-max-value,
+radioNetwork:unknown-old-en-gNB-UE-X2AP-ID,
+radioNetwork:pDCP-Overload]
+    NodebIdentity:
+      properties:
+        globalNbId:
+          properties:
+            nbId:
+              type: string
+            plmnId:
+              type: string
+          type: object
+        inventoryName:
+          type: string
+      type: object
+    GetNodebResponse:
+      properties:
+        connectionStatus:
+          oneOf:
+            - type: string
+            - type: integer
+        enb:
+          properties:
+            enbType:
+              oneOf:
+                - type: string
+                - type: integer
+            guGroupIds:
+              items:
+                type: string
+              type: array
+            servedCells:
+              items:
+                properties:
+                  bandwidthReducedSi:
+                    oneOf:
+                      - type: string
+                      - type: integer
+                  broadcastPlmns:
+                    items:
+                      type: string
+                    type: array
+                  cellId:
+                    type: string
+                  choiceEutraMode:
+                    properties:
+                      fdd:
+                        properties:
+                          dlTransmissionBandwidth:
+                            oneOf:
+                              - type: string
+                              - type: integer
+                          dlearFcn:
+                            type: integer
+                          ulTransmissionBandwidth:
+                            oneOf:
+                              - type: string
+                              - type: integer
+                          ulearFcn:
+                            type: integer
+                        additionalProperties: false
+                        type: object
+                      tdd:
+                        properties:
+                          additionalSpecialSubframeExtensionInfo:
+                            properties:
+                              additionalSpecialSubframePatternsExtension:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                              cyclicPrefixDl:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                              cyclicPrefixUl:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                            additionalProperties: false
+                            type: object
+                          additionalSpecialSubframeInfo:
+                            properties:
+                              additionalSpecialSubframePatterns:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                              cyclicPrefixDl:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                              cyclicPrefixUl:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                            additionalProperties: false
+                            type: object
+                          earFcn:
+                            type: integer
+                          specialSubframeInfo:
+                            properties:
+                              cyclicPrefixDl:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                              cyclicPrefixUl:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                              specialSubframePatterns:
+                                oneOf:
+                                  - type: string
+                                  - type: integer
+                            additionalProperties: false
+                            type: object
+                          subframeAssignment:
+                            oneOf:
+                              - type: string
+                              - type: integer
+                          transmissionBandwidth:
+                            oneOf:
+                              - type: string
+                              - type: integer
+                        additionalProperties: false
+                        type: object
+                    additionalProperties: false
+                    type: object
+                  csgId:
+                    type: string
+                  eutraMode:
+                    oneOf:
+                      - type: string
+                      - type: integer
+                  freqBandIndicatorPriority:
+                    oneOf:
+                      - type: string
+                      - type: integer
+                  mbmsServiceAreaIdentities:
+                    items:
+                      type: string
+                    type: array
+                  mbsfnSubframeInfos:
+                    items:
+                      properties:
+                        radioframeAllocationOffset:
+                          type: integer
+                        radioframeAllocationPeriod:
+                          oneOf:
+                            - type: string
+                            - type: integer
+                        subframeAllocation:
+                          type: string
+                        subframeAllocationType:
+                          oneOf:
+                            - type: string
+                            - type: integer
+                      additionalProperties: false
+                      type: object
+                    type: array
+                  multibandInfos:
+                    items:
+                      type: integer
+                    type: array
+                  neighbourInfos:
+                    items:
+                      properties:
+                        earFcn:
+                          type: integer
+                        ecgi:
+                          type: string
+                        pci:
+                          type: integer
+                        tac:
+                          type: string
+                      additionalProperties: false
+                      type: object
+                    type: array
+                  numberOfAntennaPorts:
+                    oneOf:
+                      - type: string
+                      - type: integer
+                  pci:
+                    type: integer
+                  prachConfiguration:
+                    properties:
+                      highSpeedFlag:
+                        type: boolean
+                      prachConfigurationIndex:
+                        type: integer
+                      prachFrequencyOffset:
+                        type: integer
+                      rootSequenceIndex:
+                        type: integer
+                      zeroCorrelationZoneConfiguration:
+                        type: integer
+                    additionalProperties: false
+                    type: object
+                  tac:
+                    type: string
+                additionalProperties: false
+                type: object
+              type: array
+          additionalProperties: false
+          type: object
+        failureType:
+          oneOf:
+            - type: string
+            - type: integer
+        globalNbId:
+          properties:
+            nbId:
+              type: string
+            plmnId:
+              type: string
+          additionalProperties: false
+          type: object
+        gnb:
+          properties:
+            servedNrCells:
+              items:
+                properties:
+                  nrNeighbourInfos:
+                    items:
+                      properties:
+                        choiceNrMode:
+                          properties:
+                            fdd:
+                              properties:
+                                dlarFcnFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                                ularFcnFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                              additionalProperties: false
+                              type: object
+                            tdd:
+                              properties:
+                                arFcnNrFreqInfo:
+                                  properties:
+                                    frequencyBands:
+                                      items:
+                                        properties:
+                                          nrFrequencyBand:
+                                            type: integer
+                                          supportedSulBands:
+                                            items:
+                                              type: integer
+                                            type: array
+                                        additionalProperties: false
+                                        type: object
+                                      type: array
+                                    nrArFcn:
+                                      oneOf:
+                                        - type: integer
+                                    sulInformation:
+                                      properties:
+                                        sulArFcn:
+                                          oneOf:
+                                            - type: integer
+                                        sulTransmissionBandwidth:
+                                          properties:
+                                            ncnrb:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                            nrscs:
+                                              oneOf:
+                                                - type: string
+                                                - type: integer
+                                          additionalProperties: false
+                                          type: object
+                                      additionalProperties: false
+                                      type: object
+                                  additionalProperties: false
+                                  type: object
+                              additionalProperties: false
+                              type: object
+                          additionalProperties: false
+                          type: object
+                        configuredStac:
+                          type: string
+                        nrCgi:
+                          type: string
+                        nrMode:
+                          oneOf:
+                            - type: string
+                            - type: integer
+                        nrPci:
+                          type: integer
+                        stac5g:
+                          type: string
+                      additionalProperties: false
+                      type: object
+                    type: array
+                  servedNrCellInformation:
+                    properties:
+                      cellId:
+                        type: string
+                      choiceNrMode:
+                        properties:
+                          fdd:
+                            properties:
+                              dlFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              dlTransmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                              ulFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              ulTransmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                            additionalProperties: false
+                            type: object
+                          tdd:
+                            properties:
+                              nrFreqInfo:
+                                properties:
+                                  frequencyBands:
+                                    items:
+                                      properties:
+                                        nrFrequencyBand:
+                                          type: integer
+                                        supportedSulBands:
+                                          items:
+                                            type: integer
+                                          type: array
+                                      additionalProperties: false
+                                      type: object
+                                    type: array
+                                  nrArFcn:
+                                    oneOf:
+                                      - type: integer
+                                  sulInformation:
+                                    properties:
+                                      sulArFcn:
+                                        oneOf:
+                                          - type: integer
+                                      sulTransmissionBandwidth:
+                                        properties:
+                                          ncnrb:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                          nrscs:
+                                            oneOf:
+                                              - type: string
+                                              - type: integer
+                                        additionalProperties: false
+                                        type: object
+                                    additionalProperties: false
+                                    type: object
+                                additionalProperties: false
+                                type: object
+                              transmissionBandwidth:
+                                properties:
+                                  ncnrb:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                  nrscs:
+                                    oneOf:
+                                      - type: string
+                                      - type: integer
+                                additionalProperties: false
+                                type: object
+                            additionalProperties: false
+                            type: object
+                        additionalProperties: false
+                        type: object
+                      configuredStac:
+                        type: string
+                      nrMode:
+                        oneOf:
+                          - type: string
+                          - type: integer
+                      nrPci:
+                        type: integer
+                      servedPlmns:
+                        items:
+                          type: string
+                        type: array
+                      stac5g:
+                        type: string
+                    additionalProperties: false
+                    type: object
+                additionalProperties: false
+                type: object
+              type: array
+          additionalProperties: false
+          type: object
+        ip:
+          type: string
+        nodeType:
+          oneOf:
+            - type: string
+            - type: integer
+        port:
+          type: integer
+        ranName:
+          type: string
+        setupFailure:
+          properties:
+            criticalityDiagnostics:
+              properties:
+                informationElementCriticalityDiagnostics:
+                  items:
+                    properties:
+                      ieCriticality:
+                        oneOf:
+                          - type: string
+                          - type: integer
+                      ieId:
+                        type: integer
+                      typeOfError:
+                        oneOf:
+                          - type: string
+                          - type: integer
+                    additionalProperties: false
+                    type: object
+                  type: array
+                procedureCode:
+                  type: integer
+                procedureCriticality:
+                  oneOf:
+                    - type: string
+                    - type: integer
+                triggeringMessage:
+                  oneOf:
+                    - type: string
+                    - type: integer
+              additionalProperties: false
+              type: object
+            miscellaneousCause:
+              oneOf:
+                - type: string
+                - type: integer
+            networkLayerCause:
+              oneOf:
+                - type: string
+                - type: integer
+            protocolCause:
+              oneOf:
+                - type: string
+                - type: integer
+            timeToWait:
+              oneOf:
+                - type: string
+                - type: integer
+            transportLayerCause:
+              oneOf:
+                - type: string
+                - type: integer
+          additionalProperties: false
+          type: object
+      additionalProperties: false
+      type: object
+    ErrorResponse:
+      type: object
+      required:
+        - errorCode
+        - errorMessage
+      properties:
+        errorCode:
+          type: string
+          description: '401 - corrupted json, 402 - validation error, 403 - RAN in wrong state, 404 - resource not found, 500 - RNIB error, 501 - internal problem, 502 - RMR error'
+        errorMessage:
+          type: string
+          description: Human readable text
diff --git a/router.txt b/router.txt
deleted file mode 100644 (file)
index b80e438..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-newrt|start
-rte|10060|10.0.2.15:38000
-rte|10360|10.0.2.15:38000
-rte|10061|10.0.2.15:3801
-rte|10361|10.0.2.15:3801
-rte|10062|10.0.2.15:3801
-rte|10362|10.0.2.15:3801
-rte|1080|10.0.2.15:3801
-rte|10020|10.0.2.15:3801
-rte|10370|10.0.2.15:3801
-rte|10371|10.0.2.15:38000
-rte|10372|10.0.2.15:38000
-rte|10080|10.0.2.15:3801
-rte|10081|10.0.2.15:38000
-rte|10082|10.0.2.15:38000
-rte|1100|10.0.2.15:3801
-newrt|end
diff --git a/tools/xapp_mock/Dockerfile b/tools/xapp_mock/Dockerfile
new file mode 100644 (file)
index 0000000..48c07ae
--- /dev/null
@@ -0,0 +1,45 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   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 nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:1-u16.04-nng1.1.1 as ubuntu
+
+WORKDIR /opt/xapp_mock
+COPY . . 
+ENV PATH=$PATH:/usr/local/go/bin:/usr/lib/go-1.12/bin
+# Install RMr library and dev files
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/master/packages/debian/stretch/rmr_1.3.0_amd64.deb/download.deb
+RUN dpkg -i rmr_1.3.0_amd64.deb
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/master/packages/debian/stretch/rmr-dev_1.3.0_amd64.deb/download.deb
+RUN dpkg -i rmr-dev_1.3.0_amd64.deb
+
+RUN go get github.com/pkg/errors 
+RUN go build main/xapp_mock.go 
+    
+
+
+FROM ubuntu:16.04
+COPY --from=ubuntu /opt/xapp_mock/xapp_mock /opt/xapp_mock/xapp_mock
+COPY --from=ubuntu /opt/xapp_mock/resources /opt/xapp_mock/resources
+COPY --from=ubuntu /usr/local/lib/librmr_nng.so.1 /usr/local/lib/librmr_nng.so.1
+COPY --from=ubuntu /usr/local/lib/libnng.so.1 /usr/local/lib/libnng.so.1
+WORKDIR /opt/xapp_mock
+ENV LD_LIBRARY_PATH=/usr/local/lib 
+ENV RMR_SEED_RT=resources/router.txt
+ENV RMR_PORT=5001
+#CMD mkdir -p resources/conf  exec ./xapp_mock
+CMD mkdir -p resources/conf &&  exec /bin/bash 
diff --git a/tools/xapp_mock/configuration.json b/tools/xapp_mock/configuration.json
new file mode 100644 (file)
index 0000000..9df43a1
--- /dev/null
@@ -0,0 +1,4 @@
+[ 
+       {“id”: “RIC_X2_SETUP_REQ” , “rmrMessageType”: 10060, “transactionId”: “e2e$”, “payloadHeader”: “$ranIp|$ranPort|$ranName|#packedPayload|”,  “packedPayload”: "3137322e31372e302e357c353537377c74657374327c34367c0006002a000002001500080013302300fffff000140017000001f700133023fffff0000000133023000000000001" },
+       {“id”: “RIC_ENB_CONF_UPDATE_ACK_positive” ,  “rmrMessageType”: 10081, “transactionId”: “e2e$”, “payloadHeader”: “$ranIp|$ranPort|$ranName|#packedPayload|”,  “packedPayload”: "2025000a00000100f70003000000" } 
+]
diff --git a/tools/xapp_mock/frontend/configfile.go b/tools/xapp_mock/frontend/configfile.go
new file mode 100644 (file)
index 0000000..f332a0c
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+package frontend
+
+import (
+       "github.com/pkg/errors"
+       "io/ioutil"
+       "os"
+       "path/filepath"
+       "strings"
+)
+
+func ProcessConfigurationFile(resourcesFolder, inputFolder,  suffix string, processor func(data []byte) error) error {
+       cwd, err := os.Getwd()
+       if err != nil {
+               return errors.New(err.Error())
+       }
+       inputDir := filepath.Join(cwd, resourcesFolder, inputFolder)
+
+       files, err := ioutil.ReadDir(inputDir)
+       if err != nil {
+               return errors.New(err.Error())
+       }
+
+       for _, file := range files {
+               if file.Mode().IsRegular() && strings.HasSuffix(strings.ToLower(file.Name()), suffix) {
+                       filespec := filepath.Join(inputDir, file.Name())
+
+                       data, err := ioutil.ReadFile(filespec)
+                       if err != nil {
+                               return errors.New(err.Error())
+                       }
+
+                       err = processor(data)
+                       if err != nil {
+                               return err
+                       }
+               }
+       }
+
+       return nil
+}
diff --git a/tools/xapp_mock/frontend/jsonDecoder.go b/tools/xapp_mock/frontend/jsonDecoder.go
new file mode 100644 (file)
index 0000000..0609db2
--- /dev/null
@@ -0,0 +1,80 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+package frontend
+
+import (
+       "bytes"
+       "encoding/json"
+       "fmt"
+       "github.com/pkg/errors"
+       "io"
+)
+
+const (
+       SendRmrMessage  = "send"
+       ReceiveRmrMessage  = "receive"
+)
+
+
+type JsonCommand struct {
+ Id string
+ RmrMessageType  string
+ TransactionId string
+ RanName string
+ RanIp string
+ RanPort int
+ PayloadHeader string
+ PackedPayload string
+ Payload string
+ Action string
+ WaitForRmrMessageType string
+}
+
+// Id -> Command
+var Configuration = make(map[string]*JsonCommand)
+// Rmr Message Id -> Command
+var WaitedForRmrMessageType = make(map[int]*JsonCommand)
+
+func JsonCommandDecoder(data []byte, processor func (*JsonCommand) error ) error {
+       dec := json.NewDecoder(bytes.NewReader(data))
+       var cmd JsonCommand
+       if err := dec.Decode(&cmd); err != nil && err != io.EOF {
+               return errors.New(err.Error())
+       }
+       if err := processor (&cmd); err != nil {
+               return err
+       }
+       return nil
+}
+
+func JsonCommandsDecoder(data []byte, processor func (*JsonCommand) error ) error {
+       dec := json.NewDecoder(bytes.NewReader(data))
+       for {
+               var commands []JsonCommand
+               if err := dec.Decode(&commands); err == io.EOF {
+                       break
+               } else if err != nil {
+                       return errors.New(err.Error())
+               }
+               for i, cmd := range commands {
+                       if err := processor(&cmd); err != nil {
+                               return errors.New(fmt.Sprintf("processing error at #%d, %s",i,err))
+                       }
+               }
+       }
+       return nil
+}
diff --git a/tools/xapp_mock/main/xapp_mock.go b/tools/xapp_mock/main/xapp_mock.go
new file mode 100644 (file)
index 0000000..ae2c601
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+package main
+
+import (
+       "../frontend"
+       "../rmr"
+       "../sender"
+       "flag"
+       "fmt"
+       "github.com/pkg/errors"
+       "log"
+       "os"
+       "strconv"
+)
+
+const (
+       ENV_RMR_PORT = "RMR_PORT"
+       RMR_PORT_DEFAULT = 5001
+)
+
+var rmrService *rmr.Service
+
+func main() {
+       var rmrContext *rmr.Context
+
+       var rmrConfig rmr.Config = rmr.Config{Port: RMR_PORT_DEFAULT, MaxMsgSize: rmr.RMR_MAX_MSG_SIZE, MaxRetries: 3, Flags: 0}
+       if port, err := strconv.ParseUint(os.Getenv(ENV_RMR_PORT), 10, 16); err == nil {
+               rmrConfig.Port = int(port)
+       } else {
+               log.Printf("%s: %s, using default (%d).", ENV_RMR_PORT, err,RMR_PORT_DEFAULT)
+       }
+       rmrService = rmr.NewService(rmrConfig, rmrContext)
+
+       /* Load configuration file*/
+       err := frontend.ProcessConfigurationFile("resources","conf",  ".json",
+               func(data []byte) error {
+                       return  frontend.JsonCommandsDecoder(data,jsonCommandsDecoderCB)
+               })
+       if err != nil {
+               log.Fatalf("processing Error: %s", err)
+       }
+
+       log.Print("xapp_mock is up and running.")
+
+       cmd:= flag.Arg(0) /*first remaining argument after flags have been processed*/
+       if err :=  frontend.JsonCommandDecoder([]byte(cmd),jsonCommandDecoderCB); err != nil {
+               log.Printf("command processing Error: %s", err)
+       }
+
+       rmrService.CloseContext()
+
+       log.Print("xapp_mock is down.")
+}
+
+
+// TODO: move callbacks to Dispatcher.
+func jsonCommandsDecoderCB(command *frontend.JsonCommand) error {
+       if len(command.Id) == 0{
+               return errors.New(fmt.Sprintf("invalid command, no Id"))
+       }
+       frontend.Configuration[command.Id] = command
+       if rmrMsgId, err := rmr.MessageIdToUint(command.WaitForRmrMessageType); err != nil {
+               return errors.New(fmt.Sprintf("invalid rmr message id: %s",command.WaitForRmrMessageType))
+       } else {
+               frontend.WaitedForRmrMessageType[int(rmrMsgId)] = command
+       }
+       return nil
+}
+
+// TODO: merge command with configuration
+func jsonCommandDecoderCB(command *frontend.JsonCommand) error {
+       if len(command.Id) == 0{
+               return errors.New(fmt.Sprintf("invalid command, no Id"))
+       }
+       switch command.Action {
+       case frontend.SendRmrMessage:
+               if  err := sender.SendJsonRmrMessage(*command, nil, rmrService); err != nil {
+                       return err
+               }
+               if len(command.WaitForRmrMessageType) > 0 {
+                       rmrService.ListenAndHandle() //TODO: handle error
+               }
+       case frontend.ReceiveRmrMessage:
+               if rmrMsgId, err := rmr.MessageIdToUint(command.RmrMessageType); err != nil {
+                       return errors.New(fmt.Sprintf("invalid rmr message id: %s",command.WaitForRmrMessageType))
+               } else {
+                       frontend.WaitedForRmrMessageType[int(rmrMsgId)] = command
+               }
+               rmrService.ListenAndHandle() //TODO: handle error
+       default:
+               return errors.New(fmt.Sprintf("invalid command action %s", command.Action))
+       }
+       return nil
+}
\ No newline at end of file
diff --git a/tools/xapp_mock/resources/router.txt b/tools/xapp_mock/resources/router.txt
new file mode 100644 (file)
index 0000000..1d3fea3
--- /dev/null
@@ -0,0 +1,4 @@
+newrt|start
+rte|1001|10.0.2.15:38000
+rte|2002|10.0.2.15:3801
+newrt|end
diff --git a/tools/xapp_mock/resp b/tools/xapp_mock/resp
new file mode 100644 (file)
index 0000000..01f2657
--- /dev/null
@@ -0,0 +1 @@
+20060043000002001500080002f82900007a8000140030010000630002f8290007ab50102002f8290000010001330000640002f9290007ac50203202f82902f929000002000344
diff --git a/tools/xapp_mock/rmr/rmrCgoApi.go b/tools/xapp_mock/rmr/rmrCgoApi.go
new file mode 100644 (file)
index 0000000..7686ea8
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package rmr
+
+// #cgo LDFLAGS: -L/usr/local/lib -lrmr_nng -lnng
+// #include <rmr/rmr.h>
+// #include <stdlib.h>
+import "C"
+import (
+       "fmt"
+       "github.com/pkg/errors"
+       "time"
+       "unsafe"
+)
+
+func (*Context) Init(port string, maxMsgSize int, maxRetries int, flags int) *Messenger {
+       pp := C.CString(port)
+       defer C.free(unsafe.Pointer(pp))
+       ctx := NewContext(maxMsgSize, maxRetries, flags, C.rmr_init(pp, C.int(maxMsgSize), C.int(flags)))
+       start := time.Now()
+       for !ctx.IsReady() {
+               time.Sleep(time.Second)
+               if time.Since(start) >= time.Minute {
+                       start = time.Now()
+               }
+       }
+       // Configure the rmr to make rounds of attempts to send a message before notifying the application that it should retry.
+       // Each round is about 1000 attempts with a short sleep between each round.
+       C.rmr_set_stimeout(ctx.RmrCtx, C.int(0))
+       r := Messenger(ctx)
+       return &r
+}
+
+func (ctx *Context) SendMsg(msg *MBuf) (*MBuf, error) {
+
+       allocatedCMBuf, err := ctx.getAllocatedCRmrMBuf(msg, ctx.MaxMsgSize)
+       if err != nil{
+               return nil, err
+       }
+       if state := allocatedCMBuf.state; state != RMR_OK {
+               errorMessage := fmt.Sprintf("#rmrCgoApi.SendMsg - Failed to get allocated message. state: %v - %s", state, states[int(state)])
+               return nil, errors.New(errorMessage)
+       }
+       defer C.rmr_free_msg(allocatedCMBuf)
+
+       for i:=0; i < ctx.MaxRetries; i++ {
+               currCMBuf := C.rmr_send_msg(ctx.RmrCtx, allocatedCMBuf)
+               if state := currCMBuf.state; state != RMR_OK {
+                       if state != RMR_ERR_RETRY {
+                               errorMessage := fmt.Sprintf("#rmrCgoApi.SendMsg - Failed to send message. state: %v - %s", state, states[int(state)])
+                               return nil, errors.New(errorMessage)
+                       }
+                       time.Sleep(100*time.Millisecond)
+                       continue
+               }
+               return convertToMBuf(currCMBuf)
+       }
+
+       return nil, errors.New(fmt.Sprintf("#rmrCgoApi.SendMsg - Too many retries"))
+}
+
+func (ctx *Context) RecvMsg() (*MBuf, error) {
+       allocatedCMBuf, err :=C.rmr_alloc_msg(ctx.RmrCtx, C.int(ctx.MaxMsgSize))
+       if err != nil{
+               return nil, err
+       }
+       if state := allocatedCMBuf.state;state != RMR_OK {
+               errorMessage := fmt.Sprintf("#rmrCgoApi.SendMsg - Failed to get allocated message. state: %v - %s", state, states[int(state)])
+               return nil, errors.New(errorMessage)
+       }
+       defer C.rmr_free_msg(allocatedCMBuf)
+
+       currCMBuf := C.rmr_rcv_msg(ctx.RmrCtx, allocatedCMBuf)
+       if state := currCMBuf.state; state != RMR_OK {
+               errorMessage := fmt.Sprintf("#rmrCgoApi.RecvMsg - Failed to receive message. state: %v - %s", state, states[int(state)])
+               return nil, errors.New(errorMessage)
+       }
+
+       return convertToMBuf(currCMBuf)
+}
+
+
+func (ctx *Context) IsReady() bool {
+       return int(C.rmr_ready(ctx.RmrCtx)) != 0
+}
+
+func (ctx *Context) Close() {
+       C.rmr_close(ctx.RmrCtx)
+}
diff --git a/tools/xapp_mock/rmr/rmrCgoTypes.go b/tools/xapp_mock/rmr/rmrCgoTypes.go
new file mode 100644 (file)
index 0000000..54d4f8f
--- /dev/null
@@ -0,0 +1,123 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package rmr
+
+// #cgo LDFLAGS: -L/usr/local/lib -lrmr_nng -lnng
+// #include <rmr/rmr.h>
+// #include <stdlib.h>
+import "C"
+import (
+       "fmt"
+       "unsafe"
+)
+
+func NewMBuf(mType int, len int, payload []byte, xAction []byte) *MBuf {
+       return &MBuf{
+               MType:   mType,
+               Len:     len,
+               Payload: payload,
+               XAction: xAction,
+       }
+}
+
+func NewContext(maxMsgSize int, maxRetries, flags int, ctx unsafe.Pointer) *Context {
+       return &Context{
+               MaxMsgSize: maxMsgSize,
+               MaxRetries: maxRetries,
+               Flags:      flags,
+               RmrCtx:     ctx,
+       }
+}
+
+const (
+       RMR_MAX_XACTION_LEN = int(C.RMR_MAX_XID)
+       RMR_MAX_MSG_SIZE    = int(C.RMR_MAX_RCV_BYTES)
+       RMR_MAX_MEID_LEN    = int(C.RMR_MAX_MEID)
+
+       //states
+       RMR_OK             = C.RMR_OK
+       RMR_ERR_BADARG     = C.RMR_ERR_BADARG
+       RMR_ERR_NOENDPT    = C.RMR_ERR_NOENDPT
+       RMR_ERR_EMPTY      = C.RMR_ERR_EMPTY
+       RMR_ERR_NOHDR      = C.RMR_ERR_NOHDR
+       RMR_ERR_SENDFAILED = C.RMR_ERR_SENDFAILED
+       RMR_ERR_CALLFAILED = C.RMR_ERR_CALLFAILED
+       RMR_ERR_NOWHOPEN   = C.RMR_ERR_NOWHOPEN
+       RMR_ERR_WHID       = C.RMR_ERR_WHID
+       RMR_ERR_OVERFLOW   = C.RMR_ERR_OVERFLOW
+       RMR_ERR_RETRY      = C.RMR_ERR_RETRY
+       RMR_ERR_RCVFAILED  = C.RMR_ERR_RCVFAILED
+       RMR_ERR_TIMEOUT    = C.RMR_ERR_TIMEOUT
+       RMR_ERR_UNSET      = C.RMR_ERR_UNSET
+       RMR_ERR_TRUNC      = C.RMR_ERR_TRUNC
+       RMR_ERR_INITFAILED = C.RMR_ERR_INITFAILED
+)
+
+var states = map[int]string{
+       RMR_OK:             "state is good",
+       RMR_ERR_BADARG:     "argument passd to function was unusable",
+       RMR_ERR_NOENDPT:    "send/call could not find an endpoint based on msg type",
+       RMR_ERR_EMPTY:      "msg received had no payload; attempt to send an empty message",
+       RMR_ERR_NOHDR:      "message didn't contain a valid header",
+       RMR_ERR_SENDFAILED: "send failed; errno has nano reason",
+       RMR_ERR_CALLFAILED: "unable to send call() message",
+       RMR_ERR_NOWHOPEN:   "no wormholes are open",
+       RMR_ERR_WHID:       "wormhole id was invalid",
+       RMR_ERR_OVERFLOW:   "operation would have busted through a buffer/field size",
+       RMR_ERR_RETRY:      "request (send/call/rts) failed, but caller should retry (EAGAIN for wrappers)",
+       RMR_ERR_RCVFAILED:  "receive failed (hard error)",
+       RMR_ERR_TIMEOUT:    "message processing call timed out",
+       RMR_ERR_UNSET:      "the message hasn't been populated with a transport buffer",
+       RMR_ERR_TRUNC:      "received message likely truncated",
+       RMR_ERR_INITFAILED: "initialisation of something (probably message) failed",
+}
+
+type MBuf struct {
+       MType   int
+       Len     int
+       Meid    string //Managed entity id (RAN name)*/
+       Payload []byte
+       XAction []byte
+}
+
+
+func (m MBuf) String() string {
+       return fmt.Sprintf("{ MType: %d, Len: %d, Meid: %q, Xaction: %q, Payload: [%x] }", m.MType, m.Len, m.Meid, m.XAction, m.Payload)
+}
+
+
+type Context struct {
+       MaxMsgSize     int
+       MaxRetries     int
+       Flags          int
+       RmrCtx         unsafe.Pointer
+}
+
+type Messenger interface {
+       Init(port string, maxMsgSize int, maxRetries int, flags int) *Messenger
+       SendMsg(msg *MBuf) (*MBuf, error)
+       RecvMsg() (*MBuf, error)
+       IsReady() bool
+       Close()
+}
+type Config struct {
+       Port       int
+       MaxMsgSize int
+       MaxRetries int
+       Flags      int
+}
diff --git a/tools/xapp_mock/rmr/rmrCgoUtils.go b/tools/xapp_mock/rmr/rmrCgoUtils.go
new file mode 100644 (file)
index 0000000..9b56785
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+
+package rmr
+
+// #cgo LDFLAGS: -L/usr/local/lib -lrmr_nng -lnng
+// #include <rmr/rmr.h>
+// #include <stdlib.h>
+import "C"
+import (
+       "bytes"
+       "encoding/binary"
+       "fmt"
+       "github.com/pkg/errors"
+       "strconv"
+       "strings"
+       "unsafe"
+)
+
+/*
+Allocates an mBuf and initialize it with the content of C.rmr_mbuf_t.
+The xAction field is assigned a a value without trailing spaces.
+*/
+func convertToMBuf( m *C.rmr_mbuf_t) (*MBuf, error) {
+       payloadArr := C.GoBytes(unsafe.Pointer(m.payload),C.int(m.len))
+       xActionArr := C.GoBytes(unsafe.Pointer(m.xaction),C.int(RMR_MAX_XACTION_LEN))
+
+       // Trim padding (space and 0)
+       xActionStr := strings.TrimRight(string(xActionArr), "\040\000")
+       xActionArr = []byte(xActionStr)
+
+       mbuf := &MBuf{
+               MType: int(m.mtype),
+               Len:   int(m.len),
+               //Payload: (*[]byte)(unsafe.Pointer(m.payload)),
+               Payload: payloadArr,
+               //XAction: (*[]byte)(unsafe.Pointer(m.xaction)),
+               XAction: xActionArr,
+       }
+
+       meidBuf := make([]byte, RMR_MAX_MEID_LEN)
+       if meidCstr := C.rmr_get_meid(m, (*C.uchar)(unsafe.Pointer(&meidBuf[0]))); meidCstr != nil {
+               mbuf.Meid =     strings.TrimRight(string(meidBuf), "\000")
+       }
+
+       return mbuf, nil
+}
+
+/*
+Allocates an C.rmr_mbuf_t and initialize it with the content of mBuf.
+The xAction field is padded with trailing spaces upto capacity
+*/
+func (ctx *Context) getAllocatedCRmrMBuf( mBuf *MBuf, maxMsgSize int) (cMBuf *C.rmr_mbuf_t, rc error) {
+       var xActionBuf [RMR_MAX_XACTION_LEN]byte
+       var meidBuf[RMR_MAX_MEID_LEN]byte
+
+       cMBuf = C.rmr_alloc_msg(ctx.RmrCtx, C.int(maxMsgSize))
+       cMBuf.mtype = C.int(mBuf.MType)
+       cMBuf.len = C.int(mBuf.Len)
+
+       payloadLen := len(mBuf.Payload)
+       xActionLen := len(mBuf.XAction)
+
+       copy(xActionBuf[:], mBuf.XAction)
+       for i:= xActionLen; i < RMR_MAX_XACTION_LEN; i++{
+               xActionBuf[i] = '\040' //space
+       }
+
+       // Add padding
+       copy(meidBuf[:], mBuf.Meid)
+       for i:= len(mBuf.Meid); i < RMR_MAX_MEID_LEN; i++{
+               meidBuf[i] = 0
+       }
+
+       payloadArr := (*[1 << 30]byte)(unsafe.Pointer(cMBuf.payload))[:payloadLen:payloadLen]
+       xActionArr := (*[1 << 30]byte)(unsafe.Pointer(cMBuf.xaction))[:RMR_MAX_XACTION_LEN:RMR_MAX_XACTION_LEN]
+
+       err := binary.Read(bytes.NewReader(mBuf.Payload), binary.LittleEndian, payloadArr)
+       if err != nil {
+               return nil, errors.New(fmt.Sprintf("#rmrCgoUtils.getAllocatedCRmrMBuf - Failed to read payload to allocated RMR message buffer, %s", err))
+       }
+       err = binary.Read(bytes.NewReader(xActionBuf[:]), binary.LittleEndian, xActionArr)
+       if err != nil {
+               return nil, errors.New(fmt.Sprintf("#rmrCgoUtils.getAllocatedCRmrMBuf - Failed to read xAction data to allocated RMR message buffer, %s", err))
+       }
+
+       len := C.rmr_bytes2meid(cMBuf,  (*C.uchar)(unsafe.Pointer(&meidBuf[0])), C.int(RMR_MAX_XACTION_LEN))
+       if int(len) != RMR_MAX_MEID_LEN {
+               return nil, errors.New(
+                       "#rmrCgoUtils.getAllocatedCRmrMBuf - Failed to copy meid data to allocated RMR message buffer")
+       }
+       return cMBuf,nil
+}
+
+func MessageIdToUint(id string) (msgId uint64, err error) {
+       if len(id) == 0 {
+               msgId, err = 0, nil
+       } else{
+               msgId, err = strconv.ParseUint(id, 10, 16)
+       }
+       return
+}
\ No newline at end of file
diff --git a/tools/xapp_mock/rmr/rmrEndPoint.go b/tools/xapp_mock/rmr/rmrEndPoint.go
new file mode 100644 (file)
index 0000000..fc599a5
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+package rmr
+
+import (
+       "../frontend"
+       "log"
+       "strconv"
+)
+// RmrService holds an instance of RMR messenger as well as its configuration
+type Service struct {
+       messenger  *Messenger
+}
+
+// NewRmrService instantiates a new Rmr service instance
+func NewService(rmrConfig Config, messenger Messenger) *Service {
+       return &Service{
+               messenger: messenger.Init("tcp:"+strconv.Itoa(rmrConfig.Port), rmrConfig.MaxMsgSize, rmrConfig.MaxRetries, rmrConfig.Flags),
+       }
+}
+
+func (r *Service) SendMessage(messageType int, msg []byte, transactionId []byte) (*MBuf, error){
+       log.Printf( "SendMessage (type: %d, tid: %s, msg: %v", messageType, transactionId, msg)
+       mbuf := NewMBuf(messageType, len(msg), msg, transactionId)
+       return (*r.messenger).SendMsg(mbuf)
+}
+
+// ListenAndHandle waits for messages coming from rmr_rcv_msg and sends it to a designated message handler
+func (r *Service) ListenAndHandle() error {
+       for {
+               mbuf, err := (*r.messenger).RecvMsg()
+
+               if err != nil {
+                       return err
+               }
+
+               if _, ok := frontend.WaitedForRmrMessageType[mbuf.MType]; ok {
+                       log.Printf( "ListenAndHandle Expected msg: %s", mbuf)
+                       break
+               } else {
+                       log.Printf( "ListenAndHandle Unexpected msg: %s", mbuf)
+               }
+       }
+       return nil
+}
+
+
+func (r *Service) CloseContext() {
+       (*r.messenger).Close()
+
+}
+
+
+
diff --git a/tools/xapp_mock/sender/jsonSender.go b/tools/xapp_mock/sender/jsonSender.go
new file mode 100644 (file)
index 0000000..b68ee9d
--- /dev/null
@@ -0,0 +1,146 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// 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.
+//
+package sender
+
+import (
+       "../frontend"
+       "../rmr"
+       "fmt"
+       "github.com/pkg/errors"
+       "log"
+       "reflect"
+       "strconv"
+       "strings"
+       "sync/atomic"
+       "time"
+       "unicode"
+)
+
+var counter uint64
+
+func SendJsonRmrMessage(command frontend.JsonCommand /*the copy is modified locally*/, xAction *[]byte, r *rmr.Service) error {
+       var payload []byte
+       _, err := fmt.Sscanf(command.PackedPayload, "%x", &payload)
+       if err != nil {
+               return errors.New(fmt.Sprintf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err))
+       }
+       command.PackedPayload = string(payload)
+       command.TransactionId = expandTransactionId(command.TransactionId)
+       if len(command.TransactionId) == 0 {
+               command.TransactionId = string(*xAction)
+       }
+       command.PayloadHeader = expandPayloadHeader(command.PayloadHeader, &command)
+       rmrMsgId, err := rmr.MessageIdToUint(command.RmrMessageType)
+       if err != nil {
+               return errors.New(fmt.Sprintf("invalid rmr message id: %s",command.WaitForRmrMessageType))
+       }
+       _, err = r.SendMessage(int(rmrMsgId), append([]byte(command.PayloadHeader), payload...), []byte(command.TransactionId))
+       return err
+}
+
+/*
+ * transactionId (xAction): The value may have a fixed value or $ or <prefix>$.
+ * $ is replaced by a value generated at runtime (possibly unique per message sent).
+ * If the tag does not exist, then the mock shall use the value taken from the incoming message.
+ */
+func expandTransactionId(id string) string {
+       if len(id) == 1 && id[0] == '$' {
+               return fmt.Sprintf("%d", incAndGetCounter())
+       }
+       if len(id) > 1 && id[len(id)-1] == '$' {
+               return fmt.Sprintf("%s%d", id[:len(id)-1], incAndGetCounter())
+       }
+       return id
+}
+
+/*
+ * payloadHeader: A prefix to combine with the payload that will be the message’s payload. The value may include variables of the format $<name> or #<name> where:
+ *   $<name> expands to the value of <name> if it exists or the empty string if not.
+ *   #<name> expands to the length of the value of <name> if it exists or omitted if not.
+ * The intention is to allow the Mock to construct the payload header required by the setup messages (ranIp|ranPort|ranName|payload len|<payload>).
+ * Example: “payloadHeader”: “$ranIp|$ranPort|$ranName|#packedPayload|”
+ */
+
+func expandPayloadHeader(header string, command *frontend.JsonCommand) string {
+       var name strings.Builder
+       var expandedHeader strings.Builder
+
+       r := strings.NewReader(header)
+       ch, err := r.ReadByte()
+       for {
+               if err != nil {
+                       break
+               }
+               switch ch {
+               case '$':
+                       for {
+                               ch, err = r.ReadByte()  //on error ch == 0
+                               if unicode.IsDigit(rune(ch)) || unicode.IsLetter(rune(ch)) {
+                                       name.WriteByte(ch)
+                               } else {
+                                       if fieldValue := reflect.Indirect(reflect.ValueOf(command)).FieldByName(name.String()); fieldValue.IsValid() {
+                                               switch fieldValue.Kind() {
+                                               case reflect.String:
+                                                       expandedHeader.WriteString(fieldValue.String())
+                                               case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+                                                       expandedHeader.WriteString(strconv.FormatInt(fieldValue.Int(), 10))
+                                               case reflect.Bool:
+                                                       expandedHeader.WriteString(strconv.FormatBool(fieldValue.Bool()))
+                                               case reflect.Float64, reflect.Float32:
+                                                       expandedHeader.WriteString(fmt.Sprintf("%g", fieldValue.Float()))
+                                               default:
+                                                       log.Fatalf("invalid type for $%s, value must be a string, an int, a bool or a float", name.String())
+                                               }
+                                       }
+                                       name.Reset()
+                                       break
+                               }
+                       }
+               case '#':
+                       for {
+                               ch, err = r.ReadByte()  //on error ch == 0
+                               if unicode.IsDigit(rune(ch)) || unicode.IsLetter(rune(ch)) {
+                                       name.WriteByte(ch)
+                               } else {
+                                       if fieldValue := reflect.Indirect(reflect.ValueOf(command)).FieldByName(name.String()); fieldValue.IsValid() {
+                                               if fieldValue.Kind() == reflect.String {
+                                                       expandedHeader.WriteString(strconv.FormatInt(int64(len(fieldValue.String())), 10))
+                                               } else {
+                                                       log.Fatalf("invalid type for #%s, value must be a string", name.String())
+                                               }
+                                       }
+                                       name.Reset()
+                                       break
+                               }
+                       }
+               default:
+                       if unicode.IsPrint(rune(ch)) {
+                               expandedHeader.WriteByte(ch)
+                       }
+                       ch, err = r.ReadByte()
+               }
+       }
+       return expandedHeader.String()
+}
+
+func incAndGetCounter() uint64 {
+       return atomic.AddUint64(&counter, 1)
+}
+
+func init() {
+       counter = uint64(time.Now().Second())
+}