-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
#!/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
*** 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
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}
+++ /dev/null
-##############################################################################
-#
-# 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
-
-
-
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}
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
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
##############################################################################
*** Settings ***
-Suite Setup Prepare Enviorment
+Suite Setup Prepare Enviorment
Resource ../Resource/resource.robot
Resource ../Resource/Keywords.robot
Library OperatingSystem
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
--- /dev/null
+##############################################################################
+#
+# 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
#
##############################################################################
-redis_ip_address = 'localhost'
-redis_ip_port = 6379
+*** Settings ***
+Documentation ORAN Reset - ENDC RAN to RIC Scenario 1
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# 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
##############################################################################
*** Settings ***
-Documentation ORAN Reset - RAN to RIC Scenario 1
+Documentation ORAN Reset API - ENDC RIC to RAN
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
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
*** 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}
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
-
-
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
+
+
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
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
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
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
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
+++ /dev/null
-##############################################################################
-#
-# 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
-
-
-
+++ /dev/null
-##############################################################################
-#
-# 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
-
-
-
*** Settings ***
Documentation Keywords file
-Library ${CURDIR}/scripts.py
+Library ../Scripts/cleanup_db.py
Resource ../Resource/resource.robot
Library OperatingSystem
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}
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}
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}
+++ /dev/null
-##############################################################################
-#
-# 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
*** 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
--- /dev/null
+##############################################################################
+#
+# 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
+
--- /dev/null
+##############################################################################
+#
+# 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
+
+
+
--- /dev/null
+##############################################################################
+#
+# 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
+
+
--- /dev/null
+##############################################################################
+#
+# 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
+
+
--- /dev/null
+##############################################################################
+#
+# 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
+
--- /dev/null
+##############################################################################
+#
+# 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}
*** 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
--- /dev/null
+##############################################################################
+#
+# 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}
+
+
+
+
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
--- /dev/null
+##############################################################################
+#
+# 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
+
+
+
+
+
--- /dev/null
+##############################################################################
+#
+# 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
+
+
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
+
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 ***
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
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
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
##############################################################################
*** Settings ***
-Documentation ORAN Reset - RAN to RIC Scenario 2
+Documentation ORAN Reset - X2 RAN to RIC Scenario 1
##############################################################################
*** Settings ***
-Suite Setup Prepare Enviorment
+Suite Setup Prepare Enviorment
Resource ../Resource/resource.robot
Resource ../Resource/Keywords.robot
Library OperatingSystem
Library REST ${url}
+
+
+
*** Test Cases ***
+
Prepare Ran in Connected connectionStatus
Post Request setup node b x-2
Integer response status 204
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
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# 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
##############################################################################
*** Settings ***
-Documentation ORAN Reset API - RIC to RAN
+Documentation ORAN Reset API - X2 RIC to RAN
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
port=3800
ENV RMR_SEED_RT=router.txt
EXPOSE 3800
-CMD ["sh", "-c", "./http_server -port=$port"]
+CMD ["sh", "-c", "./main -port=$port"]
--- /dev/null
+//
+// 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)
+}
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{}
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")
--- /dev/null
+//
+// 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() })
+}
# 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
+++ /dev/null
-//
-// 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)
-}
+++ /dev/null
-//
-// 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
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)
}
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)
}
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+//
+// 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
// #include <load_information_wrapper.h>
import "C"
import (
+ "e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"unsafe"
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,
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)
--- /dev/null
+//
+// 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)
+}
// #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"
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 {
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
}
defer C.delete_pdu(pdu)
return x2SetupFailureResponseToProtobuf(pdu)
-}
+}
\ No newline at end of file
package converters
import (
- "e2mgr/e2pdus"
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
/*
Test permutations of x2 setup response to protobuf enb
- */
+*/
func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
{
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"},
{
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"},
{
},
}
+ converter := NewX2SetupFailureResponseConverter(logger)
+
for _, tc := range testCases {
t.Run(tc.packedPdu, func(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 {
// #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"
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:
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 {
}
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)
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 {
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
}
}
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 {
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])))
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))
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 {
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 {
}
}
- neighbours = append(neighbours,neighbourInfo)
+ neighbours = append(neighbours, neighbourInfo)
}
}
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)}
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))
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)
}
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:
}
}
-
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
}
defer C.delete_pdu(pdu)
return x2SetupResponseToProtobuf(pdu)
}
-
package converters
import (
- "e2mgr/e2pdus"
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
/*
Test permutations of x2 setup response to protobuf enb
- */
+*/
func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
/*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) {
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 {
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) ,
},
}
}
--- /dev/null
+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)
+}
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=
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=
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
+ "e2mgr/services/rmrsender"
"e2mgr/stateMachine"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"time"
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)
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) {
"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"
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
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()
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)
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)
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()
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()
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()
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)
}
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)
}
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+//
+// 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()
+}
--- /dev/null
+//
+// 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)
+}
)
type RequestHandler interface {
- Handle(request models.Request) error
+ Handle(request models.Request) (models.IResponse, error)
}
}
}
-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)
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 {
package httpmsghandlers
import (
+ "e2mgr/rnibBuilders"
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/e2pdus"
"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"
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) {
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)
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)
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)
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)
}
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) {
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) {
_, 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) {
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) {
sr.RanPort = 8080
sr.RanName = "RanName"
- actual := handler.Handle(sr)
+ _, actual := handler.Handle(sr)
expected := &e2managererrors.RequestValidationError{}
if reflect.TypeOf(actual) != reflect.TypeOf(expected) {
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) {
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}
}
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
+}
"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"
)
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
}
"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{}
}
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
}
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)
}
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)
}
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)
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)
}
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)
}
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)
}
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)
}
)
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
}
}
- logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT")
+ h.logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT")
}
"e2mgr/rNibWriter"
"e2mgr/rmrCgo"
"e2mgr/services"
+ "e2mgr/services/rmrsender"
"e2mgr/tests"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
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 {
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"}}
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"}}
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)
//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)
//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)
//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)
}
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
)
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,
}
}
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))
}
package rmrmsghandlers
import (
- "e2mgr/logger"
"e2mgr/models"
"fmt"
"time"
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"
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
}
// 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)
//}
// 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)
//}
// 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)
"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)
}
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, ¬ificationRequest, 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(¬ificationRequest)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+}
+
+func TestHandleEndcConfigUpdateFailure(t *testing.T) {
+ h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
- go h.Handle(log, ¬ificationRequest, 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(¬ificationRequest)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
}
)
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
+}
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)
}
notificationRequest := models.NotificationRequest{RanName: ranName}
ranReconnectionManagerMock := &mocks.RanReconnectionManagerMock{}
ranReconnectionManagerMock.On("ReconnectRan", ranName).Return(nil)
- handler := NewRanLostConnectionHandler(ranReconnectionManagerMock)
- handler.Handle(logger, ¬ificationRequest, nil)
+ handler := NewRanLostConnectionHandler(logger, ranReconnectionManagerMock)
+ handler.Handle(¬ificationRequest)
ranReconnectionManagerMock.AssertCalled(t, "ReconnectRan", ranName)
}
notificationRequest := models.NotificationRequest{RanName: ranName}
ranReconnectionManagerMock := &mocks.RanReconnectionManagerMock{}
ranReconnectionManagerMock.On("ReconnectRan", ranName).Return(errors.New("error"))
- handler := NewRanLostConnectionHandler(ranReconnectionManagerMock)
- handler.Handle(logger, ¬ificationRequest, nil)
+ handler := NewRanLostConnectionHandler(logger, ranReconnectionManagerMock)
+ handler.Handle(¬ificationRequest)
ranReconnectionManagerMock.AssertCalled(t, "ReconnectRan", ranName)
-}
\ No newline at end of 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
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
+}
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"
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 {
}
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, ¬ificationRequest, nil)
+ handler.Handle(¬ificationRequest)
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, ¬ificationRequest, nil)
+ handler.Handle(¬ificationRequest)
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
}
testContext.readerMock.On("GetNodeb", RanName).Return(nodebInfo, rnibErr)
- testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(saveNodebMockReturnValue)
- handler.Handle(testContext.logger, ¬ificationRequest, 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(¬ificationRequest)
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(¬ificationRequest)
+
+ 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)
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)
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, ¬ificationRequest, nil)
+ handler.Handle(¬ificationRequest)
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)
}
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
}
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{}
}
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, ¬ificationRequest, 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")
readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
- h.Handle(log, ¬ificationRequest, nil)
+ h.Handle(¬ificationRequest)
+ 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, ¬ificationRequest, nil)
+ h.Handle(¬ificationRequest)
+ 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)
rnibErr := &common.ResourceNotFoundError{}
readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
- h.Handle(log, ¬ificationRequest, nil)
+ h.Handle(¬ificationRequest)
+ rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
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
}
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"
"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(¬ificationRequest)
+ 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(¬ificationRequest)
+ 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(¬ificationRequest)
+ 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(¬ificationRequest)
+ rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
- h.Handle(log, ¬ificationRequest, 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(¬ificationRequest)
+ 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, ¬ificationRequest, messageChannel)
+ var nb *entities.NodebInfo
+ rnibErr := common.NewResourceNotFoundError("nodeb not found")
+ readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
- //TODO:Nothing to verify
+ h.Handle(¬ificationRequest)
+ 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, ¬ificationRequest, messageChannel)
+ readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
- //TODO:Nothing to verify
+ h.Handle(¬ificationRequest)
+ rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
"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)
}
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, ¬ificationRequest, 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(¬ificationRequest)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
+}
+
+func TestHandleX2EnbConfigUpdateFailure(t *testing.T) {
+ h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
- go h.Handle(log, ¬ificationRequest, 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(¬ificationRequest)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf)
}
--- /dev/null
+//
+// 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")
+}
--- /dev/null
+//
+// 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
+++ /dev/null
-//
-// 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")
-}
+++ /dev/null
-//
-// 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() })
-}
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
}
--- /dev/null
+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
+}
"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"
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 {
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
}
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)
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)
}
"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,
}
}
}
// 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()
}
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 {
return writerMock
}
rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider, rnibWriterProvider)
- ranSetupManager := NewRanSetupManager(logger, rmrService, rnibDataService)
+ ranSetupManager := NewRanSetupManager(logger, rmrSender, rnibDataService)
return rmrMessengerMock, writerMock, ranSetupManager
}
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)
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)
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")
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")
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")
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")
--- /dev/null
+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)
+}
--- /dev/null
+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)
+}
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)
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)
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)
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)
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)
}
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...)
--- /dev/null
+//
+// 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
+}
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
}
--- /dev/null
+//
+// 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
+
+}
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+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,
+ }
+}
--- /dev/null
+//
+// 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
+}
// 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
"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 {
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),
}
}
"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"
"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 {
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) {
package rmrmsghandlerprovider
import (
+ "e2mgr/converters"
"e2mgr/handlers/rmrmsghandlers"
+ "e2mgr/logger"
"e2mgr/managers"
"e2mgr/rmrCgo"
"e2mgr/services"
+ "e2mgr/services/rmrsender"
"fmt"
)
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),
}
}
}
return handler, nil
-
}
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"
* 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}
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 {
}
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 {
}
// 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
port: 3800
rmr:
port: 3801
- maxMsgSize: 4096
+ maxMsgSize: 65536
notificationResponseBuffer: 100
bigRedButtonTimeoutSec: 5
maxConnectionAttempts: 3
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 {
// }
// 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()
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 (
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
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
+++ /dev/null
-//
-// 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)
- }
-}
+++ /dev/null
-//
-// 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())
- }
-}
+++ /dev/null
-//
-// 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)
-}
--- /dev/null
+//
+// 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"
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{}
}
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)
}
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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
+}
+//
+// 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"
)
SaveRanLoadInformation(inventoryName string, ranLoadInformation *entities.RanLoadInformation) error
GetNodeb(ranName string) (*entities.NodebInfo, error)
GetListNodebIds() ([]*entities.NbIdentity, error)
+ PingRnib() bool
}
type rNibDataService struct {
}
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
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
if err == nil {
return
}
- if !w.isConnError(err) {
+ if !isRnibConnectionError(err) {
return err
}
if i >= attempts {
}
}
-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
}
+//
+// 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 (
"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 {
}
func TestSuccessfulSaveNodeb(t *testing.T) {
- rnibDataService, _, writerMock := setupTest(t)
+ rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
nodebInfo := &entities.NodebInfo{}
nbIdentity := &entities.NbIdentity{}
}
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)
}
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)
}
func TestSuccessfulUpdateNodebInfo(t *testing.T) {
- rnibDataService, _, writerMock := setupTest(t)
+ rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
nodebInfo := &entities.NodebInfo{}
writerMock.On("UpdateNodebInfo", nodebInfo).Return(nil)
}
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)
}
func TestSuccessfulSaveRanLoadInformation(t *testing.T) {
- rnibDataService, _, writerMock := setupTest(t)
+ rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
var ranName string = "abcd"
ranLoadInformation := &entities.RanLoadInformation{}
}
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)
}
func TestSuccessfulGetNodeb(t *testing.T) {
- rnibDataService, readerMock, _ := setupTest(t)
+ rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
invName := "abcd"
nodebInfo := &entities.NodebInfo{}
}
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)
}
func TestSuccessfulGetNodebIdList(t *testing.T) {
- rnibDataService, readerMock, _ := setupTest(t)
+ rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
nodeIds := []*entities.NbIdentity{}
readerMock.On("GetListNodebIds").Return(nodeIds, nil)
}
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()
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)
//
--- /dev/null
+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)
+}
--- /dev/null
+package utils
+
+import "time"
+
+func ElapsedTime(startTime time.Time) float64 {
+ return float64(time.Since(startTime)) / float64(time.Millisecond)
+}
--- /dev/null
+# ========================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
+++ /dev/null
-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
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+[
+ {“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" }
+]
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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
--- /dev/null
+newrt|start
+rte|1001|10.0.2.15:38000
+rte|2002|10.0.2.15:3801
+newrt|end
--- /dev/null
+20060043000002001500080002f82900007a8000140030010000630002f8290007ab50102002f8290000010001330000640002f9290007ac50203202f82902f929000002000344
--- /dev/null
+//
+// 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)
+}
--- /dev/null
+//
+// 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
+}
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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()
+
+}
+
+
+
--- /dev/null
+//
+// 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())
+}