Add R5 content to master 43/4143/1
authorss412g <shuky.har-noy@intl.att.com>
Tue, 16 Jun 2020 18:51:33 +0000 (21:51 +0300)
committerss412g <shuky.har-noy@intl.att.com>
Tue, 16 Jun 2020 18:52:02 +0000 (21:52 +0300)
Change-Id: Ibfbabbcd1ec599b69f1011a337d0979e7098ad15
Signed-off-by: ss412g <shuky.har-noy@intl.att.com>
55 files changed:
Automation/Tests/E2Term_Initialization/E2Term_Init_Message_Test.robot
Automation/Tests/E2_Setup_Failure/Enable_Ric_False_Setup_Failure.robot [new file with mode: 0644]
Automation/Tests/E2_Setup_Failure/RM_Error_Setup_Failure.robot [new file with mode: 0644]
Automation/Tests/E2_Setup_Failure/__init__.robot [new file with mode: 0644]
Automation/Tests/Get_E2T_Instances/get_e2t_instances.robot
Automation/Tests/Resource/Keywords.robot
Automation/Tests/Resource/resource.robot
Automation/Tests/Resource/scripts_variables.robot
Automation/Tests/Scripts/cleanup_db.py
Automation/Tests/Scripts/e2mdbscripts.py
Automation/Tests/SetGeneralConfiguration/__init__.robot [new file with mode: 0644]
Automation/Tests/SetGeneralConfiguration/set_general_configuration.robot [new file with mode: 0644]
E2Manager/configuration/configuration.go
E2Manager/configuration/configuration_test.go
E2Manager/container-tag.yaml
E2Manager/controllers/nodeb_controller.go
E2Manager/controllers/nodeb_controller_test.go
E2Manager/converters/endc_setup_failure_response_converter_test.go
E2Manager/converters/endc_setup_response_converter_test.go
E2Manager/converters/x2_setup_failure_response_converter_test.go
E2Manager/converters/x2_setup_response_converter.go
E2Manager/converters/x2_setup_response_converter_test.go
E2Manager/go.mod
E2Manager/go.sum
E2Manager/handlers/httpmsghandlers/set_general_configuration_handler.go [new file with mode: 0644]
E2Manager/handlers/httpmsghandlers/set_general_configuration_handler_test.go [new file with mode: 0644]
E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler.go
E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler_test.go
E2Manager/handlers/rmrmsghandlers/x2_reset_request_notification_handler.go
E2Manager/handlers/rmrmsghandlers/x2_reset_response_handler.go
E2Manager/httpserver/http_server.go
E2Manager/httpserver/http_server_test.go
E2Manager/managers/ran_connect_status_change_manager.go [new file with mode: 0644]
E2Manager/managers/ran_connect_status_change_manager_test.go [new file with mode: 0644]
E2Manager/managers/ran_list_manager.go [new file with mode: 0644]
E2Manager/mocks/nodeb_controller_mock.go
E2Manager/mocks/ran_alarm_service_mock.go [new file with mode: 0644]
E2Manager/mocks/ran_list_manager_mock.go [new file with mode: 0644]
E2Manager/mocks/rnibReaderMock.go
E2Manager/mocks/rnibWriterMock.go
E2Manager/models/cause.go [new file with mode: 0644]
E2Manager/models/e2_setup_request_message.go
E2Manager/models/e2_setup_response_message.go
E2Manager/models/general_configuration_request.go [new file with mode: 0644]
E2Manager/models/general_configuration_response.go [new file with mode: 0644]
E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go
E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go
E2Manager/rNibWriter/rNibWriter.go
E2Manager/rNibWriter/rNibWriter_test.go
E2Manager/resources/configuration.yaml
E2Manager/services/ran_alarm_service.go [new file with mode: 0644]
E2Manager/services/rnib_data_service.go
E2Manager/services/rnib_data_service_test.go
E2Manager/tests/dataProvider.go
E2Manager/tests/resources/setupRequest_gnb.xml

index b575dd8..1351df7 100644 (file)
@@ -1,3 +1,25 @@
+##############################################################################
+#
+#   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.
+#
+##############################################################################
+#
+#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
+#   platform project (RICP).
+#
+
 *** Settings ***
 Suite Setup   Prepare Enviorment
 Resource   ../Resource/resource.robot
diff --git a/Automation/Tests/E2_Setup_Failure/Enable_Ric_False_Setup_Failure.robot b/Automation/Tests/E2_Setup_Failure/Enable_Ric_False_Setup_Failure.robot
new file mode 100644 (file)
index 0000000..acada18
--- /dev/null
@@ -0,0 +1,50 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+#
+#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
+#   platform project (RICP).
+#
+
+
+*** Settings ***
+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     ../Scripts/e2mdbscripts.py
+Library     REST        ${url}
+Suite Teardown  Flush And Populate DB
+
+
+*** Test Cases ***
+
+Disable ric and restart simulator
+    ${result}    e2mdbscripts.set_enable_ric_false
+    Restart simulator
+
+
+prepare logs for tests
+    Remove log files
+    Save logs
+
+
+E2M Logs - Verify RMR Message
+    ${result}    find_rmr_message.verify_logs   ${EXECDIR}   ${e2mgr_log_filename}  ${Setup_failure_message_type}    ${None}
+    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
diff --git a/Automation/Tests/E2_Setup_Failure/RM_Error_Setup_Failure.robot b/Automation/Tests/E2_Setup_Failure/RM_Error_Setup_Failure.robot
new file mode 100644 (file)
index 0000000..aca558f
--- /dev/null
@@ -0,0 +1,60 @@
+##############################################################################
+#
+#   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.
+#
+##############################################################################
+#
+#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
+#   platform project (RICP).
+#
+
+
+*** Settings ***
+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}
+Suite Teardown  Start RoutingManager Simulator
+
+
+*** Test Cases ***
+Stop Routing manager simulator and restarting simulator
+    Stop RoutingManager Simulator
+    Restart simulator with less docker
+
+prepare logs for tests
+    Remove log files
+    Save logs
+
+Get request gnb
+    Sleep    2s
+    Get Request node b gnb
+    Integer  response status  200
+    String   response body ranName    ${ranname}
+    String   response body connectionStatus    DISCONNECTED
+    String   response body nodeType     GNB
+    Integer  response body gnb ranFunctions 0 ranFunctionId  1
+    Integer  response body gnb ranFunctions 0 ranFunctionRevision  1
+    Integer  response body gnb ranFunctions 1 ranFunctionId  2
+    Integer  response body gnb ranFunctions 1 ranFunctionRevision  1
+    Integer  response body gnb ranFunctions 2 ranFunctionId  3
+    Integer  response body gnb ranFunctions 2 ranFunctionRevision  1
+
+E2M Logs - Verify RMR Message
+    ${result}    find_rmr_message.verify_logs   ${EXECDIR}   ${e2mgr_log_filename}  ${Setup_failure_message_type}    ${None}
+    Should Be Equal As Strings    ${result}      True
\ No newline at end of file
diff --git a/Automation/Tests/E2_Setup_Failure/__init__.robot b/Automation/Tests/E2_Setup_Failure/__init__.robot
new file mode 100644 (file)
index 0000000..51e9ef6
--- /dev/null
@@ -0,0 +1,24 @@
+##############################################################################
+#
+#   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.
+#
+##############################################################################
+#
+#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
+#   platform project (RICP).
+#
+
+*** Settings ***
+Documentation    Setup Failure
index 09bc6ca..4f580c0 100644 (file)
@@ -37,7 +37,7 @@ Get E2T instances
     ${headers}=  Create Dictionary    Accept=application/json
     ${resp}=    Get Request   getE2tInstances     /v1/e2t/list    headers=${headers}
     Should Be Equal As Strings   ${resp.status_code}    200
-    Should Be Equal As Strings    ${resp.content}        [{"e2tAddress":"e2t.att.com:38000","ranNames":["test1","test2","test3"]},{"e2tAddress":"e2t.att.com:38001","ranNames":[]}]
+    Should Be Equal As Strings    ${resp.content}        [{"e2tAddress":"e2t.att.com:38000","ranNames":["test1","test2","test3"]}]
     ${flush}  cleanup_db.flush
 
 
index 46296d8..1f453df 100644 (file)
@@ -35,6 +35,9 @@ Update Ran request
     Sleep  1s
     PUT    ${update_gnb_url}   ${update_gnb_body}
 
+Set General Configuration request
+    Sleep  1s
+    PUT    ${set_general_configuration}   ${set_general_configuration_body}
 
 Update Ran request not valid
     Sleep  1s
@@ -126,3 +129,7 @@ Restart simulator with less docker
     ${result}=  Run And Return Rc And Output     ${docker_command}
     Should Be Equal As Integers    ${result[1]}    ${docker_number-1}
 
+Flush And Populate DB
+    ${flush}  cleanup_db.flush
+    Sleep  2s
+
index 29e15f8..dc33988 100644 (file)
@@ -28,8 +28,10 @@ Documentation    Resource file
 ${docker_number}    5
 ${docker_number-1}    4
 ${url}   http://localhost:3800
-${ranName}  gnb:208-092-303030
+${ranName}  gnb_208_092_303030
 ${getNodeb}  /v1/nodeb/${ranName}
+${set_general_configuration}   /v1/nodeb/parameters
+${set_general_configuration_body}   {"enableRic":false}
 ${update_gnb_url}   /v1/nodeb/${ranName}/update
 ${update_gnb_body}  {"servedNrCells":[{"servedNrCellInformation":{"cellId":"abcd","choiceNrMode":{"fdd":{}},"nrMode":1,"nrPci":1,"servedPlmns":["whatever"]},"nrNeighbourInfos":[{"nrCgi":"one","choiceNrMode":{"fdd":{}},"nrMode":1,"nrPci":1}]}]}
 ${update_gnb_body_notvalid}  {"servedNrCells":[{"servedNrCellInformation":{"choiceNrMode":{"fdd":{}},"nrMode":1,"nrPci":1,"servedPlmns":["whatever"]},"nrNeighbourInfos":[{"nrCgi":"whatever","choiceNrMode":{"fdd":{}},"nrMode":1,"nrPci":1}]}]}
index 89dc05a..99c2944 100644 (file)
@@ -32,5 +32,4 @@ ${first_retry_to_retrieve_from_db}      RnibDataService.retry - retrying 1 GetNo
 ${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
 ${E2_TERM_KEEP_ALIVE_REQ_message_type_successfully_sent}     Message type: 1101 - Successfully sent RMR message
-
-
+${save_general_configuration}      RnibDataService.SaveGeneralConfiguration - configuration: {EnableRic:false}
\ No newline at end of file
index 4dd3ff0..979da9a 100644 (file)
@@ -33,9 +33,8 @@ def flush():
     r = redis.Redis(host=c, port=p, db=0)
 
     r.flushall()
-
+    r.set("{e2Manager},GENERAL","{\"enableRic\":true}")
     r.set("{e2Manager},E2TAddresses", "[\"10.0.2.15:38000\"]")
-
     r.set("{e2Manager},E2TInstance:10.0.2.15:38000","{\"address\":\"10.0.2.15:38000\",\"associatedRanList\":[],\"keepAliveTimestamp\":" + str(int((time.time()+2) * 1000000000)) + ",\"state\":\"ACTIVE\",\"deletionTimeStamp\":0}")
 
     return True
index b452b93..b209ea3 100644 (file)
 ##############################################################################
 
 import config
-import redis
-import cleanup_db
 import json
+import redis
+
 
 def getRedisClientDecodeResponse():
     c = config.redis_ip_address
     p = config.redis_ip_port
     return redis.Redis(host=c, port=p, db=0, decode_responses=True)
 
+
 def verify_ran_is_associated_with_e2t_instance(ranName, e2tAddress):
     r = getRedisClientDecodeResponse()
-    e2tInstanceJson = r.get("{e2Manager},E2TInstance:"+e2tAddress)
+    e2tInstanceJson = r.get("{e2Manager},E2TInstance:" + e2tAddress)
     e2tInstanceDic = json.loads(e2tInstanceJson)
     assocRanList = e2tInstanceDic.get("associatedRanList")
     return ranName in assocRanList
 
+
 def verify_e2t_instance_has_no_associated_rans(e2tAddress):
     r = getRedisClientDecodeResponse()
-    e2tInstanceJson = r.get("{e2Manager},E2TInstance:"+e2tAddress)
+    e2tInstanceJson = r.get("{e2Manager},E2TInstance:" + e2tAddress)
     e2tInstanceDic = json.loads(e2tInstanceJson)
     assocRanList = e2tInstanceDic.get("associatedRanList")
     return not assocRanList
 
+
 def verify_e2t_instance_exists_in_addresses(e2tAddress):
     r = getRedisClientDecodeResponse()
     e2tAddressesJson = r.get("{e2Manager},E2TAddresses")
     e2tAddresses = json.loads(e2tAddressesJson)
     return e2tAddress in e2tAddresses
 
+
 def verify_e2t_instance_key_exists(e2tAddress):
     r = getRedisClientDecodeResponse()
-    return r.exists("{e2Manager},E2TInstance:"+e2tAddress)
+    return r.exists("{e2Manager},E2TInstance:" + e2tAddress)
+
 
 def populate_e2t_instances_in_e2m_db_for_get_e2t_instances_tc():
     r = getRedisClientDecodeResponse()
-    r.set("{e2Manager},E2TAddresses", "[\"e2t.att.com:38000\",\"e2t.att.com:38001\"]")
-    r.set("{e2Manager},E2TInstance:e2t.att.com:38000", "{\"address\":\"e2t.att.com:38000\",\"associatedRanList\":[\"test1\",\"test2\",\"test3\"],\"keepAliveTimestamp\":1577619310484022369,\"state\":\"ACTIVE\"}")
-    r.set("{e2Manager},E2TInstance:e2t.att.com:38001", "{\"address\":\"e2t.att.com:38001\",\"associatedRanList\":[],\"keepAliveTimestamp\":1577619310484022369,\"state\":\"ACTIVE\"}")
+    r.set("{e2Manager},E2TAddresses", "[\"e2t.att.com:38000\"]")
+    r.set("{e2Manager},E2TInstance:e2t.att.com:38000",
+          "{\"address\":\"e2t.att.com:38000\",\"associatedRanList\":[\"test1\",\"test2\",\"test3\"],\"keepAliveTimestamp\":1577619310484022369,\"state\":\"ACTIVE\"}")
     return True
 
-# def dissociate_ran_from_e2tInstance(ranName, e2tAddress):
-#     r = getRedisClientDecodeResponse()
-#     e2tInstanceJson = r.get("{e2Manager},E2TInstance:"+e2tAddress)
-#     e2tInstanceDic = json.loads(e2tInstanceJson)
-#     assocRanList = e2tInstanceDic.get("associatedRanList")
-#     print(assocRanList)
-#     assocRanList.remove(ranName)
-#     updatedE2tInstanceJson = json.dumps(e2tInstanceDic)
-#     print(updatedE2tInstanceJson)
-#     r.set("{e2Manager},E2TInstance:"+e2tAddress, updatedE2tInstanceJson)
-#     nodebBytes = r.get("{e2Manager},RAN:"+ranName)
-#     encoded = nodebBytes.decode().replace(e2tAddress,"").encode()
-#     r.set("{e2Manager},RAN:"+ranName, encoded)
 
+def set_enable_ric_false():
+    r = getRedisClientDecodeResponse()
+    r.set("{e2Manager},GENERAL", "{\"enableRic\":false}")
+    return True
diff --git a/Automation/Tests/SetGeneralConfiguration/__init__.robot b/Automation/Tests/SetGeneralConfiguration/__init__.robot
new file mode 100644 (file)
index 0000000..4a008d9
--- /dev/null
@@ -0,0 +1,20 @@
+##############################################################################
+#
+#   Copyright (c) 2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+*** Settings ***
+Documentation    Resource status
diff --git a/Automation/Tests/SetGeneralConfiguration/set_general_configuration.robot b/Automation/Tests/SetGeneralConfiguration/set_general_configuration.robot
new file mode 100644 (file)
index 0000000..da7356b
--- /dev/null
@@ -0,0 +1,48 @@
+##############################################################################
+#
+#   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.
+#
+##############################################################################
+#
+#   This source code is part of the near-RT RIC (RAN Intelligent Controller)
+#   platform project (RICP).
+
+
+
+*** Settings ***
+Suite Setup   Prepare Enviorment
+Resource   ../Resource/resource.robot
+Resource   ../Resource/Keywords.robot
+Library     OperatingSystem
+Library     REST        ${url}
+
+
+
+
+*** Test Cases ***
+
+prepare logs for tests
+    Remove log files
+    Save logs
+
+Set General Configuration
+    Sleep  2s
+    Set General Configuration request
+    Integer  response status  200
+    String   response body enableRic    false
+
+Verify e2mgr logs - Third retry to retrieve from db
+   ${result}    find_error_script.find_error     ${EXECDIR}  ${e2mgr_log_filename}   ${save_general_configuration}
+   Should Be Equal As Strings    ${result}      True
\ No newline at end of file
index 5e4c31e..f539c5d 100644 (file)
 package configuration
 
 import (
+       "errors"
        "fmt"
        "github.com/spf13/viper"
+       "strconv"
 )
 
 type Configuration struct {
@@ -38,10 +40,7 @@ type Configuration struct {
        RoutingManager struct {
                BaseUrl string
        }
-/*     Kubernetes struct {
-               ConfigPath string
-               KubeNamespace  string
-       }*/
+
        NotificationResponseBuffer   int
        BigRedButtonTimeoutSec       int
        MaxRnibConnectionAttempts    int
@@ -50,9 +49,11 @@ type Configuration struct {
        KeepAliveDelayMs             int
        E2TInstanceDeletionTimeoutMs int
        GlobalRicId                  struct {
-               PlmnId      string
-               RicNearRtId string
+               RicId string
+               Mcc   string
+               Mnc   string
        }
+       StateChangeMessageChannel string
 }
 
 func ParseConfiguration() *Configuration {
@@ -72,7 +73,6 @@ func ParseConfiguration() *Configuration {
        config.populateHttpConfig(viper.Sub("http"))
        config.populateLoggingConfig(viper.Sub("logging"))
        config.populateRoutingManagerConfig(viper.Sub("routingManager"))
-       //config.populateKubernetesConfig(viper.Sub("kubernetes"))
        config.NotificationResponseBuffer = viper.GetInt("notificationResponseBuffer")
        config.BigRedButtonTimeoutSec = viper.GetInt("bigRedButtonTimeoutSec")
        config.MaxRnibConnectionAttempts = viper.GetInt("maxRnibConnectionAttempts")
@@ -81,6 +81,7 @@ func ParseConfiguration() *Configuration {
        config.KeepAliveDelayMs = viper.GetInt("KeepAliveDelayMs")
        config.E2TInstanceDeletionTimeoutMs = viper.GetInt("e2tInstanceDeletionTimeoutMs")
        config.populateGlobalRicIdConfig(viper.Sub("globalRicId"))
+       config.StateChangeMessageChannel = viper.GetString("stateChangeMessageChannel")
        return &config
 }
 
@@ -113,27 +114,112 @@ func (c *Configuration) populateRoutingManagerConfig(rmConfig *viper.Viper) {
        c.RoutingManager.BaseUrl = rmConfig.GetString("baseUrl")
 }
 
-/*func (c *Configuration) populateKubernetesConfig(rmConfig *viper.Viper) {
-       if rmConfig == nil {
-               panic(fmt.Sprintf("#configuration.populateKubernetesConfig - failed to populate Kubernetes configuration: The entry 'kubernetes' not found\n"))
+func (c *Configuration) populateGlobalRicIdConfig(globalRicIdConfig *viper.Viper) {
+       err := validateGlobalRicIdConfig(globalRicIdConfig)
+       if err != nil {
+               panic(err.Error())
        }
-       c.Kubernetes.ConfigPath = rmConfig.GetString("configPath")
-       c.Kubernetes.KubeNamespace = rmConfig.GetString("kubeNamespace")
-}*/
+       c.GlobalRicId.RicId = globalRicIdConfig.GetString("ricId")
+       c.GlobalRicId.Mcc = globalRicIdConfig.GetString("mcc")
+       c.GlobalRicId.Mnc = globalRicIdConfig.GetString("mnc")
+}
 
-func (c *Configuration) populateGlobalRicIdConfig(globalRicIdConfig *viper.Viper) {
+func validateGlobalRicIdConfig(globalRicIdConfig *viper.Viper) error {
        if globalRicIdConfig == nil {
-               panic(fmt.Sprintf("#configuration.populateGlobalRicIdConfig - failed to populate Global RicId configuration: The entry 'globalRicId' not found\n"))
+               return errors.New("#configuration.validateGlobalRicIdConfig - failed to populate Global RicId configuration: The entry 'globalRicId' not found\n")
+       }
+
+       err := validateRicId(globalRicIdConfig.GetString("ricId"))
+
+       if err != nil {
+               return err
+       }
+
+       err = validateMcc(globalRicIdConfig.GetString("mcc"))
+
+       if err != nil {
+               return err
+       }
+
+       err = validateMnc(globalRicIdConfig.GetString("mnc"))
+
+       if err != nil {
+               return err
+       }
+
+
+       return nil
+}
+
+func validateMcc(mcc string) error {
+
+       if len(mcc) == 0{
+               return errors.New("#configuration.validateMcc - mcc is missing or empty\n")
+       }
+
+       if len(mcc) != 3{
+               return errors.New("#configuration.validateMcc - mcc is not 3 digits\n")
+       }
+
+       mccInt, err := strconv.Atoi(mcc)
+
+       if err != nil{
+               return errors.New("#configuration.validateMcc - mcc is not a number\n")
+       }
+
+       if mccInt < 0 {
+               return errors.New("#configuration.validateMcc - mcc is negative\n")
        }
-       c.GlobalRicId.PlmnId = globalRicIdConfig.GetString("plmnId")
-       c.GlobalRicId.RicNearRtId = globalRicIdConfig.GetString("ricNearRtId")
+       return nil
 }
 
+func validateMnc(mnc string) error {
+
+       if len(mnc) == 0{
+               return errors.New("#configuration.validateMnc - mnc is missing or empty\n")
+       }
+
+       if len(mnc) < 2 || len(mnc) >3 {
+               return errors.New("#configuration.validateMnc - mnc is not 2 or 3 digits\n")
+       }
+
+       mncAsInt, err := strconv.Atoi(mnc)
+
+       if err != nil{
+               return errors.New("#configuration.validateMnc - mnc is not a number\n")
+       }
+
+       if mncAsInt < 0 {
+               return errors.New("#configuration.validateMnc - mnc is negative\n")
+       }
+
+       return nil
+}
+
+func validateRicId(ricId string) error{
+
+       if len(ricId) == 0{
+               return errors.New("#configuration.validateRicId - ricId is missing or empty\n")
+       }
+
+       if len(ricId) != 5 {
+               return errors.New("#configuration.validateRicId - ricId length should be 5 hex characters\n")
+       }
+
+       _, err := strconv.ParseUint(ricId, 16, 64)
+       if err != nil {
+               return errors.New("#configuration.validateRicId - ricId is not hex number\n")
+       }
+
+       return nil
+}
+
+
 func (c *Configuration) String() string {
        return fmt.Sprintf("{logging.logLevel: %s, http.port: %d, rmr: { port: %d, maxMsgSize: %d}, routingManager.baseUrl: %s, "+
                "notificationResponseBuffer: %d, bigRedButtonTimeoutSec: %d, maxRnibConnectionAttempts: %d, "+
                "rnibRetryIntervalMs: %d, keepAliveResponseTimeoutMs: %d, keepAliveDelayMs: %d, e2tInstanceDeletionTimeoutMs: %d, "+
-               "globalRicId: { plmnId: %s, ricNearRtId: %s}",//, kubernetes: {configPath: %s, kubeNamespace: %s}}",
+               "globalRicId: { ricId: %s, mcc: %s, mnc: %s}, StateChangeMessageChannel: %s",
                c.Logging.LogLevel,
                c.Http.Port,
                c.Rmr.Port,
@@ -146,9 +232,9 @@ func (c *Configuration) String() string {
                c.KeepAliveResponseTimeoutMs,
                c.KeepAliveDelayMs,
                c.E2TInstanceDeletionTimeoutMs,
-               c.GlobalRicId.PlmnId,
-               c.GlobalRicId.RicNearRtId,
-/*             c.Kubernetes.ConfigPath,
-               c.Kubernetes.KubeNamespace,*/
+               c.GlobalRicId.RicId,
+               c.GlobalRicId.Mcc,
+               c.GlobalRicId.Mnc,
+               c.StateChangeMessageChannel,
        )
 }
index 695ed9a..27fd1b4 100644 (file)
@@ -40,10 +40,10 @@ func TestParseConfigurationSuccess(t *testing.T) {
        assert.Equal(t, 1500, config.KeepAliveDelayMs)
        assert.Equal(t, 15000, config.E2TInstanceDeletionTimeoutMs)
        assert.NotNil(t, config.GlobalRicId)
-       assert.NotEmpty(t, config.GlobalRicId.PlmnId)
-       assert.NotEmpty(t, config.GlobalRicId.RicNearRtId)
-/*     assert.NotEmpty(t, config.Kubernetes.KubeNamespace)
-       assert.NotEmpty(t, config.Kubernetes.ConfigPath)*/
+       assert.Equal(t, "AACCE", config.GlobalRicId.RicId)
+       assert.Equal(t, "310", config.GlobalRicId.Mcc)
+       assert.Equal(t, "411", config.GlobalRicId.Mnc)
+       assert.Equal(t, "RAN_CONNECTION_STATUS_CHANGE", config.StateChangeMessageChannel)
 }
 
 func TestStringer(t *testing.T) {
@@ -83,7 +83,7 @@ func TestRmrConfigNotFoundFailure(t *testing.T) {
        yamlMap := map[string]interface{}{
                "logging": map[string]interface{}{"logLevel": "info"},
                "http":    map[string]interface{}{"port": 3800},
-               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
                "globalRicId":    map[string]interface{}{"plmnId": "131014", "ricNearRtId": "556670"},
        }
        buf, err := yaml.Marshal(yamlMap)
@@ -113,7 +113,7 @@ func TestLoggingConfigNotFoundFailure(t *testing.T) {
        yamlMap := map[string]interface{}{
                "rmr":  map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
                "http": map[string]interface{}{"port": 3800},
-               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
                "globalRicId":    map[string]interface{}{"plmnId": "131014", "ricNearRtId": "556670"},
        }
        buf, err := yaml.Marshal(yamlMap)
@@ -144,7 +144,7 @@ func TestHttpConfigNotFoundFailure(t *testing.T) {
        yamlMap := map[string]interface{}{
                "rmr":     map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
                "logging": map[string]interface{}{"logLevel": "info"},
-               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
                "globalRicId":    map[string]interface{}{"plmnId": "131014", "ricNearRtId": "556670"},
        }
        buf, err := yaml.Marshal(yamlMap)
@@ -176,7 +176,7 @@ func TestRoutingManagerConfigNotFoundFailure(t *testing.T) {
                "rmr":     map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
                "logging": map[string]interface{}{"logLevel": "info"},
                "http": map[string]interface{}{"port": 3800},
-               "globalRicId":    map[string]interface{}{"plmnId": "131014", "ricNearRtId": "556670"},
+               "globalRicId":    map[string]interface{}{"mcc": 327, "mnc": 94, "ricId": "AACCE"},
        }
        buf, err := yaml.Marshal(yamlMap)
        if err != nil {
@@ -207,8 +207,7 @@ func TestGlobalRicIdConfigNotFoundFailure(t *testing.T) {
                "rmr":     map[string]interface{}{"port": 3801, "maxMsgSize": 4096},
                "logging": map[string]interface{}{"logLevel": "info"},
                "http": map[string]interface{}{"port": 3800},
-               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
-               //"kubernetes":    map[string]interface{}{"kubeNamespace": "test", "ConfigPath": "test"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
        }
        buf, err := yaml.Marshal(yamlMap)
        if err != nil {
@@ -218,38 +217,487 @@ func TestGlobalRicIdConfigNotFoundFailure(t *testing.T) {
        if err != nil {
                t.Errorf("#TestGlobalRicIdConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
        }
-       assert.PanicsWithValue(t, "#configuration.populateGlobalRicIdConfig - failed to populate Global RicId configuration: The entry 'globalRicId' not found\n",
+       assert.PanicsWithValue(t, "#configuration.validateGlobalRicIdConfig - failed to populate Global RicId configuration: The entry 'globalRicId' not found\n",
                func() { ParseConfiguration() })
 }
 
-/*func TestKubernetesConfigNotFoundFailure(t *testing.T) {
+func TestEmptyRicIdFailure(t *testing.T) {
+configPath := "../resources/configuration.yaml"
+configPathTmp := "../resources/configuration.yaml_tmp"
+err := os.Rename(configPath, configPathTmp)
+if err != nil {
+t.Errorf("#TestEmptyRicIdFailure - failed to rename configuration file: %s\n", configPath)
+}
+defer func() {
+err = os.Rename(configPathTmp, configPath)
+if err != nil {
+t.Errorf("#TestEmptyRicIdFailure - 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"},
+"http": map[string]interface{}{"port": 3800},
+"globalRicId":    map[string]interface{}{"mcc": "327", "mnc": "94", "ricId": ""},
+"routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+}
+buf, err := yaml.Marshal(yamlMap)
+if err != nil {
+t.Errorf("#TestEmptyRicIdFailure - failed to marshal configuration map\n")
+}
+err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+if err != nil {
+t.Errorf("#TestEmptyRicIdFailure - failed to write configuration file: %s\n", configPath)
+}
+assert.PanicsWithValue(t, "#configuration.validateRicId - ricId is missing or empty\n",
+func() { ParseConfiguration() })
+}
+
+func TestMissingRicIdFailure(t *testing.T) {
        configPath := "../resources/configuration.yaml"
        configPathTmp := "../resources/configuration.yaml_tmp"
        err := os.Rename(configPath, configPathTmp)
        if err != nil {
-               t.Errorf("#TestKubernetesConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+               t.Errorf("#TestEmptyRicIdFailure - failed to rename configuration file: %s\n", configPath)
        }
        defer func() {
                err = os.Rename(configPathTmp, configPath)
                if err != nil {
-                       t.Errorf("#TestKubernetesConfigNotFoundFailure - failed to rename configuration file: %s\n", configPath)
+                       t.Errorf("#TestEmptyRicIdFailure - 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"},
                "http": map[string]interface{}{"port": 3800},
-               "routingManager":    map[string]interface{}{"baseUrl": "http://iltlv740.intl.att.com:8080/ric/v1/handles/"},
-               "globalRicId":    map[string]interface{}{"plmnId": "131014", "ricNearRtId": "556670"},
+               "globalRicId":    map[string]interface{}{"mcc": "327", "mnc": "94"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestEmptyRicIdFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestEmptyRicIdFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateRicId - ricId is missing or empty\n",
+               func() { ParseConfiguration() })
+}
+
+func TestNonHexRicIdFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestNonHexRicIdFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestNonHexRicIdFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "327", "mnc": "94", "ricId": "TEST1"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestNonHexRicIdFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestNonHexRicIdFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateRicId - ricId is not hex number\n",
+               func() { ParseConfiguration() })
+}
+
+func TestWrongRicIdLengthFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestWrongRicIdLengthFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestWrongRicIdLengthFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "327", "mnc": "94", "ricId": "AA43"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestWrongRicIdLengthFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestWrongRicIdLengthFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateRicId - ricId length should be 5 hex characters\n",
+               func() { ParseConfiguration() })
+}
+
+func TestMccNotThreeDigitsFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestMccNotThreeDigitsFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestMccNotThreeDigitsFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "31", "mnc": "94", "ricId": "AA443"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
        }
        buf, err := yaml.Marshal(yamlMap)
        if err != nil {
-               t.Errorf("#TestKubernetesConfigNotFoundFailure - failed to marshal configuration map\n")
+               t.Errorf("#TestMccNotThreeDigitsFailure - failed to marshal configuration map\n")
        }
        err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
        if err != nil {
-               t.Errorf("#TestKubernetesConfigNotFoundFailure - failed to write configuration file: %s\n", configPath)
+               t.Errorf("#TestMccNotThreeDigitsFailure - failed to write configuration file: %s\n", configPath)
        }
-       assert.PanicsWithValue(t, "#configuration.populateKubernetesConfig - failed to populate Kubernetes configuration: The entry 'kubernetes' not found\n",
+       assert.PanicsWithValue(t, "#configuration.validateMcc - mcc is not 3 digits\n",
                func() { ParseConfiguration() })
-}*/
+}
+
+func TestMncLengthIsGreaterThanThreeDigitsFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestMncLengthIsGreaterThanThreeDigitsFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestMncLengthIsGreaterThanThreeDigitsFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "310", "mnc": "6794", "ricId": "AA443"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestMncLengthIsGreaterThanThreeDigitsFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestMncLengthIsGreaterThanThreeDigitsFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMnc - mnc is not 2 or 3 digits\n",
+               func() { ParseConfiguration() })
+}
+
+func TestMncLengthIsLessThanTwoDigitsFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestMncLengthIsLessThanTwoDigitsFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestMncLengthIsLessThanTwoDigitsFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "310", "mnc": "4", "ricId": "AA443"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestMncLengthIsLessThanTwoDigitsFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestMncLengthIsLessThanTwoDigitsFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMnc - mnc is not 2 or 3 digits\n",
+               func() { ParseConfiguration() })
+}
+
+func TestNegativeMncFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestNegativeMncFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestNegativeMncFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "310", "mnc": "-2", "ricId": "AA443"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestNegativeMncFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestNegativeMncFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMnc - mnc is negative\n",
+               func() { ParseConfiguration() })
+}
+
+func TestNegativeMccFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestNegativeMncFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestNegativeMncFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "-31", "mnc": "222", "ricId": "AA443"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestNegativeMncFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestNegativeMncFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMcc - mcc is negative\n",
+               func() { ParseConfiguration() })
+}
+
+func TestAlphaNumericMccFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestAlphaNumericMccFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestAlphaNumericMccFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "1W2", "mnc": "222", "ricId": "AA443"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestAlphaNumericMccFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestAlphaNumericMccFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMcc - mcc is not a number\n",
+               func() { ParseConfiguration() })
+}
+
+func TestAlphaNumericMncFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestAlphaNumericMncFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestAlphaNumericMncFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "111", "mnc": "2A8", "ricId": "AA443"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestAlphaNumericMncFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestAlphaNumericMncFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMnc - mnc is not a number\n",
+               func() { ParseConfiguration() })
+}
+
+func TestMissingMmcFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestMissingMmcFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestMissingMmcFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mnc": "94", "ricId": "AABB3"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestMissingMmcFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestMissingMmcFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMcc - mcc is missing or empty\n",
+               func() { ParseConfiguration() })
+}
+
+
+func TestEmptyMmcFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestEmptyMmcFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestEmptyMmcFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "", "mnc": "94", "ricId": "AABB3"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestEmptyMmcFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestEmptyMmcFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMcc - mcc is missing or empty\n",
+               func() { ParseConfiguration() })
+}
+
+func TestEmptyMncFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestEmptyMncFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestEmptyMncFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "111", "mnc": "", "ricId": "AABB3"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestEmptyMncFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestEmptyMncFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMnc - mnc is missing or empty\n",
+               func() { ParseConfiguration() })
+}
+
+func TestMissingMncFailure(t *testing.T) {
+       configPath := "../resources/configuration.yaml"
+       configPathTmp := "../resources/configuration.yaml_tmp"
+       err := os.Rename(configPath, configPathTmp)
+       if err != nil {
+               t.Errorf("#TestMissingMncFailure - failed to rename configuration file: %s\n", configPath)
+       }
+       defer func() {
+               err = os.Rename(configPathTmp, configPath)
+               if err != nil {
+                       t.Errorf("#TestMissingMncFailure - 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"},
+               "http": map[string]interface{}{"port": 3800},
+               "globalRicId":    map[string]interface{}{"mcc": "111", "ricId": "AABB3"},
+               "routingManager":    map[string]interface{}{"baseUrl": "http://localhost:8080/ric/v1/handles/"},
+       }
+       buf, err := yaml.Marshal(yamlMap)
+       if err != nil {
+               t.Errorf("#TestMissingMncFailure - failed to marshal configuration map\n")
+       }
+       err = ioutil.WriteFile("../resources/configuration.yaml", buf, 0644)
+       if err != nil {
+               t.Errorf("#TestMissingMncFailure - failed to write configuration file: %s\n", configPath)
+       }
+       assert.PanicsWithValue(t, "#configuration.validateMnc - mnc is missing or empty\n",
+               func() { ParseConfiguration() })
+}
index ccff1ff..273b7ac 100644 (file)
@@ -1,4 +1,4 @@
 # The Jenkins job requires a tag to build the Docker image.
 # Global-JJB script assumes this file is in the repo root.
 ---
-tag: 4.4.12
+tag: 5.2.0
index 90b9311..49e821d 100644 (file)
@@ -40,6 +40,8 @@ const (
        ParamRanName = "ranName"
        LimitRequest = 2000
 )
+const ApplicationJson = "application/json"
+const ContentType = "Content-Type"
 
 type INodebController interface {
        Shutdown(writer http.ResponseWriter, r *http.Request)
@@ -49,6 +51,7 @@ type INodebController interface {
        GetNodeb(writer http.ResponseWriter, r *http.Request)
        UpdateGnb(writer http.ResponseWriter, r *http.Request)
        GetNodebIdList(writer http.ResponseWriter, r *http.Request)
+       SetGeneralConfiguration(writer http.ResponseWriter, r *http.Request)
 }
 
 type NodebController struct {
@@ -90,11 +93,22 @@ func (c *NodebController) UpdateGnb(writer http.ResponseWriter, r *http.Request)
                return
        }
 
-       request.Gnb = &gnb;
+       request.Gnb = &gnb
        request.RanName = ranName
        c.handleRequest(writer, &r.Header, httpmsghandlerprovider.UpdateGnbRequest, request, true)
 }
 
+func (c *NodebController) SetGeneralConfiguration(writer http.ResponseWriter, r *http.Request) {
+       c.logger.Infof("[Client -> E2 Manager] #NodebController.SetGeneralConfiguration - request: %v", c.prettifyRequest(r))
+
+       request := models.GeneralConfigurationRequest{}
+
+       if !c.extractJsonBody(r, &request, writer){
+               return
+       }
+       c.handleRequest(writer, &r.Header, httpmsghandlerprovider.SetGeneralConfigurationRequest, 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)
@@ -210,13 +224,13 @@ func (c *NodebController) handleRequest(writer http.ResponseWriter, header *http
        }
 
        c.logger.Infof("[E2 Manager -> Client] #NodebController.handleRequest - response: %s", result)
-       writer.Header().Set("Content-Type", "application/json")
+       writer.Header().Set(ContentType, ApplicationJson)
        writer.Write(result)
 }
 
 func (c *NodebController) validateRequestHeader(header *http.Header) error {
 
-       if header.Get("Content-Type") != "application/json" {
+       if header.Get(ContentType) != ApplicationJson {
                c.logger.Errorf("#NodebController.validateRequestHeader - validation failure, incorrect content type")
 
                return e2managererrors.NewHeaderValidationError()
@@ -281,7 +295,7 @@ func (c *NodebController) handleErrorResponse(err error, writer http.ResponseWri
 
        c.logger.Errorf("[E2 Manager -> Client] #NodebController.handleErrorResponse - http status: %d, error response: %+v", httpError, errorResponseDetails)
 
-       writer.Header().Set("Content-Type", "application/json")
+       writer.Header().Set(ContentType, ApplicationJson)
        writer.WriteHeader(httpError)
        _, err = writer.Write(errorResponse)
 }
index a9bccdc..1543674 100644 (file)
@@ -277,6 +277,39 @@ func TestShutdownHandlerRnibError(t *testing.T) {
        assert.Equal(t, errorResponse.Code, e2managererrors.NewRnibDbError().Code)
 }
 
+func TestSetGeneralConfigurationHandlerRnibError(t *testing.T) {
+       controller, readerMock, _, _, _ := setupControllerTest(t)
+
+       configuration := &entities.GeneralConfiguration{}
+       readerMock.On("GetGeneralConfiguration").Return(configuration, e2managererrors.NewRnibDbError())
+
+       writer := httptest.NewRecorder()
+
+       httpRequest, _ := http.NewRequest("PUT", "https://localhost:3800/v1/nodeb/parameters", strings.NewReader("{\"enableRic\":false}"))
+
+       controller.SetGeneralConfiguration(writer, httpRequest)
+
+       var errorResponse = parseJsonRequest(t, writer.Body)
+
+       assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+       assert.Equal(t, e2managererrors.NewRnibDbError().Code, errorResponse.Code)
+}
+
+func TestSetGeneralConfigurationInvalidJson(t *testing.T) {
+       controller, _, _, _, _ := setupControllerTest(t)
+
+       writer := httptest.NewRecorder()
+
+       httpRequest, _ := http.NewRequest("PUT", "https://localhost:3800/v1/nodeb/parameters", strings.NewReader("{}{}"))
+
+       controller.SetGeneralConfiguration(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 controllerGetNodebTestExecuter(t *testing.T, context *controllerGetNodebTestContext) {
        controller, readerMock, _, _, _ := setupControllerTest(t)
        writer := httptest.NewRecorder()
index 77c60b5..ac5aa52 100644 (file)
@@ -25,6 +25,7 @@ import (
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "regexp"
        "strings"
        "testing"
 )
@@ -42,7 +43,7 @@ func TestUnpackEndcX2SetupFailureResponseAndExtract(t *testing.T) {
                failure   error
        }{
                {
-                       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 > > ",
+                       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
@@ -110,10 +111,14 @@ func TestUnpackEndcX2SetupFailureResponseAndExtract(t *testing.T) {
                                nb.SetupFailure = response
                                nb.FailureType = entities.Failure_X2_SETUP_FAILURE
                                respStr := fmt.Sprintf("%s %s", nb.ConnectionStatus, response)
-                               if !strings.EqualFold(respStr, tc.response) {
-                                       t.Errorf("want: response=[%s], got: [%s]", tc.response, respStr)
-                               }
 
+                               space := regexp.MustCompile(`\s+`)
+                               s1 := space.ReplaceAllString(respStr, " ")
+                               s2 := space.ReplaceAllString(tc.response," ")
+
+                               if !strings.EqualFold(s1, s2) {
+                                       t.Errorf("want: [%s], got: [%s]", tc.response, respStr)
+                               }
                        }
                })
        }
index f68e4c0..d4b2848 100644 (file)
@@ -25,6 +25,7 @@ import (
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "regexp"
        "strings"
        "testing"
 )
@@ -44,7 +45,7 @@ func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
        }{
                {
                        key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"},
-                       gnb: "CONNECTED [served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" stac5g:\"3d44d3\" configured_stac:\"4e4f\" served_plmns:\"3e4e5e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS60 ncnrb:NRB107 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS30 ncnrb:NRB133 > > > >  served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" stac5g:\"3d44d3\" configured_stac:\"4e4f\" served_plmns:\"3e4e5e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB121 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB132 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"1e3f27:1f2e3d4ff0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB11 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > > > > ]",
+                       gnb: "CONNECTED [served_nr_cell_information:{nr_pci:5  cell_id:\"1e3f27:1f2e3d4ff0\"  stac5g:\"3d44d3\"  configured_stac:\"4e4f\"  served_plmns:\"3e4e5e\"  nr_mode:TDD  choice_nr_mode:{tdd:{nr_freq_info:{nr_ar_fcn:1  sulInformation:{sul_ar_fcn:2  sul_transmission_bandwidth:{nrscs:SCS60  ncnrb:NRB107}}  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}  transmission_bandwidth:{nrscs:SCS30  ncnrb:NRB133}}}} served_nr_cell_information:{nr_pci:5  cell_id:\"1e3f27:1f2e3d4ff0\"  stac5g:\"3d44d3\"  configured_stac:\"4e4f\"  served_plmns:\"3e4e5e\"  nr_mode:TDD  choice_nr_mode:{tdd:{nr_freq_info:{nr_ar_fcn:1  sulInformation:{sul_ar_fcn:2  sul_transmission_bandwidth:{nrscs:SCS120  ncnrb:NRB121}}  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}  transmission_bandwidth:{nrscs:SCS15  ncnrb:NRB132}}}}  nr_neighbour_infos:{nr_pci:44  nr_cgi:\"1e3f27:1f2e3d4ff0\"  nr_mode:TDD  choice_nr_mode:{tdd:{ar_fcn_nr_freq_info:{nr_ar_fcn:1  sulInformation:{sul_ar_fcn:2  sul_transmission_bandwidth:{nrscs:SCS15  ncnrb:NRB11}}  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}}}}]",
                        /*
                E2AP-PDU:
                         successfulOutcome_t
@@ -153,7 +154,7 @@ func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "202400808e00000100f600808640000200fc00090002f829504a952a0a00fd007200010c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a000211e148033e4e5e4c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a00021a0044033e4e5e000000002c001e3f271f2e3d4ff0031e3f274400010000150400000a00020000"},
                {
                        key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"},
-                       gnb: "CONNECTED [served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" stac5g:\"3d44d3\" configured_stac:\"4e4f\" served_plmns:\"3e4e5e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS30 ncnrb:NRB107 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB121 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"1e3f27:1f2e3d4ff0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:5 sulInformation:<sul_ar_fcn:6 sul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB18 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > > > > ]",
+                       gnb: "CONNECTED [served_nr_cell_information:{nr_pci:5  cell_id:\"1e3f27:1f2e3d4ff0\"  stac5g:\"3d44d3\"  configured_stac:\"4e4f\"  served_plmns:\"3e4e5e\"  nr_mode:TDD  choice_nr_mode:{tdd:{nr_freq_info:{nr_ar_fcn:1  sulInformation:{sul_ar_fcn:2  sul_transmission_bandwidth:{nrscs:SCS30  ncnrb:NRB107}}  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}  transmission_bandwidth:{nrscs:SCS15  ncnrb:NRB121}}}}  nr_neighbour_infos:{nr_pci:44  nr_cgi:\"1e3f27:1f2e3d4ff0\"  nr_mode:TDD  choice_nr_mode:{tdd:{ar_fcn_nr_freq_info:{nr_ar_fcn:5  sulInformation:{sul_ar_fcn:6  sul_transmission_bandwidth:{nrscs:SCS120  ncnrb:NRB18}}  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}}}}]",
                        /*
                        E2AP-PDU:
                         successfulOutcome_t
@@ -234,7 +235,7 @@ func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
 
                {
                        key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"},
-                       gnb: "CONNECTED [served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" stac5g:\"3d44d3\" configured_stac:\"4e4f\" served_plmns:\"3e4e5e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS60 ncnrb:NRB107 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS30 ncnrb:NRB133 > > > >  served_nr_cell_information:<nr_pci:8 cell_id:\"2e3f45:1f2e3d4ff0\" stac5g:\"4faa3c\" configured_stac:\"1a2f\" served_plmns:\"50321e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:4 sulInformation:<sul_ar_fcn:8 sul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB121 > > frequency_bands:<nr_frequency_band:7 supported_sul_bands:3 > > transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB132 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"1e3f27:1f2e3d4ff0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB11 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > > > > ]",
+                       gnb: "CONNECTED [served_nr_cell_information:{nr_pci:5  cell_id:\"1e3f27:1f2e3d4ff0\"  stac5g:\"3d44d3\"  configured_stac:\"4e4f\"  served_plmns:\"3e4e5e\"  nr_mode:TDD  choice_nr_mode:{tdd:{nr_freq_info:{nr_ar_fcn:1  sulInformation:{sul_ar_fcn:2  sul_transmission_bandwidth:{nrscs:SCS60  ncnrb:NRB107}}  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}  transmission_bandwidth:{nrscs:SCS30  ncnrb:NRB133}}}} served_nr_cell_information:{nr_pci:8  cell_id:\"2e3f45:1f2e3d4ff0\"  stac5g:\"4faa3c\"  configured_stac:\"1a2f\"  served_plmns:\"50321e\"  nr_mode:TDD  choice_nr_mode:{tdd:{nr_freq_info:{nr_ar_fcn:4  sulInformation:{sul_ar_fcn:8  sul_transmission_bandwidth:{nrscs:SCS120  ncnrb:NRB121}}  frequency_bands:{nr_frequency_band:7  supported_sul_bands:3}}  transmission_bandwidth:{nrscs:SCS15  ncnrb:NRB132}}}}  nr_neighbour_infos:{nr_pci:44  nr_cgi:\"1e3f27:1f2e3d4ff0\"  nr_mode:TDD  choice_nr_mode:{tdd:{ar_fcn_nr_freq_info:{nr_ar_fcn:1  sulInformation:{sul_ar_fcn:2  sul_transmission_bandwidth:{nrscs:SCS15  ncnrb:NRB11}}  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}}}}]",
                        /*
                        E2AP-PDU:
                         successfulOutcome_t
@@ -343,7 +344,7 @@ func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
 
                {
                        key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"},
-                       gnb: "CONNECTED [served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" served_plmns:\"3e4e5e\" nr_mode:FDD choice_nr_mode:<fdd:<ul_freq_info:<nr_ar_fcn:5 frequency_bands:<nr_frequency_band:44 supported_sul_bands:33 > > dl_freq_info:<nr_ar_fcn:1 frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > ul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB11 > dl_transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB135 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"1e3f27:1f2e3d4ff0\" nr_mode:FDD choice_nr_mode:<fdd:<ular_fcn_freq_info:<nr_ar_fcn:5 frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > dlar_fcn_freq_info:<nr_ar_fcn:1 frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > > > > ]",
+                       gnb: "CONNECTED [served_nr_cell_information:{nr_pci:5  cell_id:\"1e3f27:1f2e3d4ff0\"  served_plmns:\"3e4e5e\"  nr_mode:FDD  choice_nr_mode:{fdd:{ul_freq_info:{nr_ar_fcn:5  frequency_bands:{nr_frequency_band:44  supported_sul_bands:33}}  dl_freq_info:{nr_ar_fcn:1  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}  ul_transmission_bandwidth:{nrscs:SCS120  ncnrb:NRB11}  dl_transmission_bandwidth:{nrscs:SCS15  ncnrb:NRB135}}}}  nr_neighbour_infos:{nr_pci:44  nr_cgi:\"1e3f27:1f2e3d4ff0\"  nr_mode:FDD  choice_nr_mode:{fdd:{ular_fcn_freq_info:{nr_ar_fcn:5  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}  dlar_fcn_freq_info:{nr_ar_fcn:1  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}}}}]",
                        /*
                        E2AP-PDU:
                         successfulOutcome_t
@@ -433,7 +434,7 @@ func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
 
                {
                        key: &entities.GlobalNbId{PlmnId: "04a5c1", NbId: "4fc52bff"},
-                       gnb: "CONNECTED [served_nr_cell_information:<nr_pci:9 cell_id:\"aeafa7:2a3e3b4cd0\" stac5g:\"7d4773\" configured_stac:\"477f\" served_plmns:\"7e7e7e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:8 sulInformation:<sul_ar_fcn:9 sul_transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB121 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS60 ncnrb:NRB18 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"5a5ff1:2a3e3b4cd0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:5 sulInformation:<sul_ar_fcn:6 sul_transmission_bandwidth:<nrscs:SCS30 ncnrb:NRB18 > > frequency_bands:<nr_frequency_band:4 supported_sul_bands:3 > > > > > nr_neighbour_infos:<nr_pci:9 nr_cgi:\"5d5caa:af3e354ac0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:7 sulInformation:<sul_ar_fcn:8 sul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB25 > > frequency_bands:<nr_frequency_band:3 supported_sul_bands:1 > > > > > ]",
+                       gnb: "CONNECTED [served_nr_cell_information:{nr_pci:9  cell_id:\"aeafa7:2a3e3b4cd0\"  stac5g:\"7d4773\"  configured_stac:\"477f\"  served_plmns:\"7e7e7e\"  nr_mode:TDD  choice_nr_mode:{tdd:{nr_freq_info:{nr_ar_fcn:8  sulInformation:{sul_ar_fcn:9  sul_transmission_bandwidth:{nrscs:SCS15  ncnrb:NRB121}}  frequency_bands:{nr_frequency_band:22  supported_sul_bands:11}}  transmission_bandwidth:{nrscs:SCS60  ncnrb:NRB18}}}}  nr_neighbour_infos:{nr_pci:44  nr_cgi:\"5a5ff1:2a3e3b4cd0\"  nr_mode:TDD  choice_nr_mode:{tdd:{ar_fcn_nr_freq_info:{nr_ar_fcn:5  sulInformation:{sul_ar_fcn:6  sul_transmission_bandwidth:{nrscs:SCS30  ncnrb:NRB18}}  frequency_bands:{nr_frequency_band:4  supported_sul_bands:3}}}}}  nr_neighbour_infos:{nr_pci:9  nr_cgi:\"5d5caa:af3e354ac0\"  nr_mode:TDD  choice_nr_mode:{tdd:{ar_fcn_nr_freq_info:{nr_ar_fcn:7  sulInformation:{sul_ar_fcn:8  sul_transmission_bandwidth:{nrscs:SCS120  ncnrb:NRB25}}  frequency_bands:{nr_frequency_band:3  supported_sul_bands:1}}}}}]",
                        /*
                        E2AP-PDU:
                         successfulOutcome_t
@@ -602,8 +603,13 @@ func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
                                nb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
                                nb.Configuration = &entities.NodebInfo_Gnb{Gnb: gnb}
                                gnbStr := fmt.Sprintf("%s %s", nb.ConnectionStatus, gnb.ServedNrCells)
-                               if !strings.EqualFold(gnbStr, tc.gnb) {
-                                       t.Errorf("want: enb=%s, got: %s", tc.gnb, gnbStr)
+
+                               space := regexp.MustCompile(`\s+`)
+                               s1 := space.ReplaceAllString(gnbStr, " ")
+                               s2 := space.ReplaceAllString(tc.gnb," ")
+
+                               if !strings.EqualFold(s1, s2) {
+                                       t.Errorf("want: [%s], got: [%s]", tc.gnb, gnbStr)
                                }
 
                        }
index 54a1f53..3f4cebd 100644 (file)
@@ -25,6 +25,7 @@ import (
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "regexp"
        "strings"
        "testing"
 )
@@ -42,7 +43,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                failure   error
        }{
                {
-                       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 > > ",
+                       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
@@ -74,7 +75,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                        */
                        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 > > ",
+                       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
@@ -102,7 +103,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                        */
                        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 > > ",
+                       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
@@ -130,7 +131,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                        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 > > ",
+                       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
@@ -157,7 +158,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                        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 > > ",
+                       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
@@ -188,7 +189,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
 
 
                {
-                       response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED criticality_diagnostics:<procedure_code:33 > ",
+                       response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED  criticality_diagnostics:{procedure_code:33}",
                        /*
                                E2AP-PDU:
                                 unsuccessfulOutcome_t
@@ -210,7 +211,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                        packedPdu: "4006000e0000020005400168001140024021"},
 
                {
-                       response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED ",
+                       response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED",
                        /*
                                E2AP-PDU:
                                 unsuccessfulOutcome_t
@@ -226,7 +227,7 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                        */
                        packedPdu: "400600080000010005400168"},
                {
-                       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 > > ",
+                       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
@@ -294,8 +295,13 @@ func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
                                nb.SetupFailure = response
                                nb.FailureType = entities.Failure_X2_SETUP_FAILURE
                                respStr := fmt.Sprintf("%s %s", nb.ConnectionStatus, response)
-                               if !strings.EqualFold(respStr, tc.response) {
-                                       t.Errorf("want: response=[%s], got: [%s]", tc.response, respStr)
+
+                               space := regexp.MustCompile(`\s+`)
+                               s1 := space.ReplaceAllString(respStr, " ")
+                               s2 := space.ReplaceAllString(tc.response," ")
+
+                               if !strings.EqualFold(s1, s2) {
+                                       t.Errorf("want: [%s], got: [%s]", tc.response, respStr)
                                }
 
                        }
index 2ce50b4..e98523f 100644 (file)
@@ -44,6 +44,8 @@ const (
        maxnoofNeighbours                = 512
 )
 
+const Format = "%02x:%02x"
+
 type X2SetupResponseConverter struct {
        logger *logger.Logger
 }
@@ -293,7 +295,7 @@ func getServedCellsNeighbour_Info(neighbour_Information *C.Neighbour_Information
                        //pLMN_Identity:eUTRANcellIdentifier
                        plmnId := C.GoBytes(unsafe.Pointer(member.eCGI.pLMN_Identity.buf), C.int(member.eCGI.pLMN_Identity.size))
                        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 := &entities.NeighbourInformation{Ecgi: fmt.Sprintf(Format, plmnId, eUTRANcellIdentifier)}
 
                        neighbourInfo.Pci = uint32(member.pCI)
 
@@ -334,7 +336,7 @@ func getServedCells(servedCellsIE *C.ServedCells_t) ([]*entities.ServedCellInfo,
                        //pLMN_Identity:eUTRANcellIdentifier
                        plmnId := C.GoBytes(unsafe.Pointer(member.servedCellInfo.cellId.pLMN_Identity.buf), C.int(member.servedCellInfo.cellId.pLMN_Identity.size))
                        eUTRANcellIdentifier := C.GoBytes(unsafe.Pointer(member.servedCellInfo.cellId.eUTRANcellIdentifier.buf), C.int(member.servedCellInfo.cellId.eUTRANcellIdentifier.size))
-                       servedCellInfo.CellId = fmt.Sprintf("%02x:%02x", plmnId, eUTRANcellIdentifier)
+                       servedCellInfo.CellId = fmt.Sprintf(Format, plmnId, eUTRANcellIdentifier)
 
                        servedCellInfo.Tac = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(member.servedCellInfo.tAC.buf), C.int(member.servedCellInfo.tAC.size)))
 
@@ -388,7 +390,7 @@ func getGUGroupIDList(guGroupIDList *C.GUGroupIDList_t) []string {
                for _, guGroupID := range guGroupIDList_slice {
                        plmnId := C.GoBytes(unsafe.Pointer(guGroupID.pLMN_Identity.buf), C.int(guGroupID.pLMN_Identity.size))
                        mME_Group_ID := C.GoBytes(unsafe.Pointer(guGroupID.mME_Group_ID.buf), C.int(guGroupID.mME_Group_ID.size))
-                       ids = append(ids, fmt.Sprintf("%02x:%02x", plmnId, mME_Group_ID))
+                       ids = append(ids, fmt.Sprintf(Format, plmnId, mME_Group_ID))
                }
        }
 
index 8161747..739a412 100644 (file)
@@ -25,6 +25,7 @@ import (
        "e2mgr/logger"
        "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "regexp"
        "strings"
        "testing"
 )
@@ -44,7 +45,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
        }{
                {
                        key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -82,7 +83,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "2006002a000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"},
                {
                        key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD  pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:<fdd:<ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75 > > eutra_mode:FDD ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD pci:100  cell_id:\"02f929:0007ac50\"  tac:\"0203\"  broadcast_plmns:\"02f829\"  broadcast_plmns:\"02f929\"  choice_eutra_mode:{fdd:{ulear_fcn:2  dlear_fcn:3  ul_transmission_bandwidth:BW75  dl_transmission_bandwidth:BW75}}  eutra_mode:FDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -136,7 +137,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "20060043000002001500080002f82900007a8000140030010000630002f8290007ab50102002f8290000010001330000640002f9290007ac50203202f82902f929000002000344"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:2 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:2  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -178,7 +179,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        */
                        packedPdu: "20060033000002001500080002f82900007a8000140020000000630002f8290007ab50102002f8291000010001330000005f0003800102"},
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD ] [02f729:0203 02f929:0304]",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD] [02f729:0203 02f929:0304]",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -226,7 +227,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "2006003a000003001500080002f82900007a8000140017000000630002f8290007ab50102002f8290000010001330018000c1002f72902030002f9290304"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<tdd:<ear_fcn:1 transmission_bandwidth:BW50 subframe_assignment:SA2 special_subframe_info:<special_subframe_patterns:SSP4 cyclic_prefix_dl:NORMAL cyclic_prefix_ul:EXTENDED > > > eutra_mode:TDD ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{tdd:{ear_fcn:1  transmission_bandwidth:BW50  subframe_assignment:SA2  special_subframe_info:{special_subframe_patterns:SSP4  cyclic_prefix_dl:NORMAL  cyclic_prefix_ul:EXTENDED}}}  eutra_mode:TDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -266,7 +267,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        */
                        packedPdu: "2006002a000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829400001320820"},
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<tdd:<ear_fcn:1 transmission_bandwidth:BW50 subframe_assignment:SA2 special_subframe_info:<special_subframe_patterns:SSP4 cyclic_prefix_dl:EXTENDED cyclic_prefix_ul:NORMAL > additional_special_subframe_info:<additional_special_subframe_patterns:SSP9 cyclic_prefix_dl:NORMAL cyclic_prefix_ul:EXTENDED > > > eutra_mode:TDD ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{tdd:{ear_fcn:1  transmission_bandwidth:BW50  subframe_assignment:SA2  special_subframe_info:{special_subframe_patterns:SSP4  cyclic_prefix_dl:EXTENDED  cyclic_prefix_ul:NORMAL}  additional_special_subframe_info:{additional_special_subframe_patterns:SSP9  cyclic_prefix_dl:NORMAL  cyclic_prefix_ul:EXTENDED}}}  eutra_mode:TDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -315,7 +316,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "20060032000002001500080002f82900007a800014001f000000630002f8290007ab50102002f8295000013208800000006140021220"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<tdd:<ear_fcn:2 transmission_bandwidth:BW50 subframe_assignment:SA2 special_subframe_info:<special_subframe_patterns:SSP4 cyclic_prefix_dl:EXTENDED cyclic_prefix_ul:NORMAL > > > eutra_mode:TDD ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{tdd:{ear_fcn:2  transmission_bandwidth:BW50  subframe_assignment:SA2  special_subframe_info:{special_subframe_patterns:SSP4  cyclic_prefix_dl:EXTENDED  cyclic_prefix_ul:NORMAL}}}  eutra_mode:TDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -361,7 +362,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "20060033000002001500080002f82900007a8000140020000000630002f8290007ab50102002f8295000013208800000005e0003800102"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<tdd:<ear_fcn:1 transmission_bandwidth:BW50 subframe_assignment:SA2 special_subframe_info:<special_subframe_patterns:SSP4 cyclic_prefix_dl:EXTENDED cyclic_prefix_ul:NORMAL > additional_special_subframe_extension_info:<additional_special_subframe_patterns_extension:SSP10 cyclic_prefix_dl:NORMAL cyclic_prefix_ul:NORMAL > > > eutra_mode:TDD ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:{tdd:{ear_fcn:1 transmission_bandwidth:BW50 subframe_assignment:SA2 special_subframe_info:{special_subframe_patterns:SSP4 cyclic_prefix_dl:EXTENDED cyclic_prefix_ul:NORMAL} additional_special_subframe_extension_info:{additional_special_subframe_patterns_extension:SSP10 cyclic_prefix_dl:NORMAL cyclic_prefix_ul:NORMAL}}} eutra_mode:TDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -410,7 +411,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "20060031000002001500080002f82900007a800014001e000000630002f8290007ab50102002f829500001320880000000b3400100"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<tdd:<ear_fcn:2 transmission_bandwidth:BW50 subframe_assignment:SA2 special_subframe_info:<special_subframe_patterns:SSP4 cyclic_prefix_dl:EXTENDED cyclic_prefix_ul:NORMAL > additional_special_subframe_info:<additional_special_subframe_patterns:SSP9 cyclic_prefix_dl:NORMAL cyclic_prefix_ul:EXTENDED > additional_special_subframe_extension_info:<additional_special_subframe_patterns_extension:SSP10 cyclic_prefix_dl:NORMAL cyclic_prefix_ul:NORMAL > > > eutra_mode:TDD ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:{tdd:{ear_fcn:2 transmission_bandwidth:BW50 subframe_assignment:SA2 special_subframe_info:{special_subframe_patterns:SSP4 cyclic_prefix_dl:EXTENDED cyclic_prefix_ul:NORMAL} additional_special_subframe_info:{additional_special_subframe_patterns:SSP9 cyclic_prefix_dl:NORMAL cyclic_prefix_ul:EXTENDED} additional_special_subframe_extension_info:{additional_special_subframe_patterns_extension:SSP10 cyclic_prefix_dl:NORMAL cyclic_prefix_ul:NORMAL}}} eutra_mode:TDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -471,7 +472,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "2006003e000002001500080002f82900007a800014002b000000630002f8290007ab50102002f829500001320880000200b3400100006140021220005e0003800102"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80b0"},
-                       enb: "CONNECTED HOME_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD number_of_antenna_ports:AN1  pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:<fdd:<ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75 > > eutra_mode:FDD ] []",
+                       enb: "CONNECTED HOME_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:{fdd:{ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50}} eutra_mode:FDD number_of_antenna_ports:AN1 pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:{fdd:{ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75}} eutra_mode:FDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -531,7 +532,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "2006004b000002001500090002f82940007a80b000140037010800630002f8290007ab50102002f829000001000133000000294001000000640002f9290007ac50203202f82902f929000002000344"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a40"},
-                       enb: "CONNECTED SHORT_MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD number_of_antenna_ports:AN1  pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:<fdd:<ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75 > > eutra_mode:FDD prach_configuration:<root_sequence_index:15 zero_correlation_zone_configuration:7 high_speed_flag:true prach_frequency_offset:30 > ] []",
+                       enb: "CONNECTED SHORT_MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD  number_of_antenna_ports:AN1 pci:100  cell_id:\"02f929:0007ac50\"  tac:\"0203\"  broadcast_plmns:\"02f829\"  broadcast_plmns:\"02f929\"  choice_eutra_mode:{fdd:{ulear_fcn:2  dlear_fcn:3  ul_transmission_bandwidth:BW75  dl_transmission_bandwidth:BW75}}  eutra_mode:FDD  prach_configuration:{root_sequence_index:15  zero_correlation_zone_configuration:7  high_speed_flag:true  prach_frequency_offset:30}] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -600,7 +601,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "20060056000002001500090002f8298003007a4000140042010800630002f8290007ab50102002f829000001000133000000294001000800640002f9290007ac50203202f82902f92900000200034400000037400500000f79e0"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a40"},
-                       enb: "CONNECTED SHORT_MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD number_of_antenna_ports:AN1  pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:<fdd:<ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75 > > eutra_mode:FDD mbsfn_subframe_infos:<radioframe_allocation_period:N8 radioframe_allocation_offset:3 subframe_allocation:\"28\" subframe_allocation_type:ONE_FRAME > ] []",
+                       enb: "CONNECTED SHORT_MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD  number_of_antenna_ports:AN1 pci:100  cell_id:\"02f929:0007ac50\"  tac:\"0203\"  broadcast_plmns:\"02f829\"  broadcast_plmns:\"02f929\"  choice_eutra_mode:{fdd:{ulear_fcn:2  dlear_fcn:3  ul_transmission_bandwidth:BW75  dl_transmission_bandwidth:BW75}}  eutra_mode:FDD  mbsfn_subframe_infos:{radioframe_allocation_period:N8  radioframe_allocation_offset:3  subframe_allocation:\"28\"  subframe_allocation_type:ONE_FRAME}] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -668,7 +669,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        */
                        packedPdu: "20060054000002001500090002f8298003007a4000140040010800630002f8290007ab50102002f829000001000133000000294001000800640002f9290007ac50203202f82902f929000002000344000000384003019850"},
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a40"},
-                       enb: "CONNECTED SHORT_MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD number_of_antenna_ports:AN1 mbsfn_subframe_infos:<radioframe_allocation_period:N8 radioframe_allocation_offset:3 subframe_allocation:\"28\" subframe_allocation_type:ONE_FRAME >  pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:<fdd:<ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75 > > eutra_mode:FDD ] []",
+                       enb: "CONNECTED SHORT_MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD  number_of_antenna_ports:AN1  mbsfn_subframe_infos:{radioframe_allocation_period:N8  radioframe_allocation_offset:3  subframe_allocation:\"28\"  subframe_allocation_type:ONE_FRAME} pci:100  cell_id:\"02f929:0007ac50\"  tac:\"0203\"  broadcast_plmns:\"02f829\"  broadcast_plmns:\"02f929\"  choice_eutra_mode:{fdd:{ulear_fcn:2  dlear_fcn:3  ul_transmission_bandwidth:BW75  dl_transmission_bandwidth:BW75}}  eutra_mode:FDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -735,7 +736,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        */
                        packedPdu: "20060052000002001500090002f8298003007a400014003e010800630002f8290007ab50102002f82900000100013300010029400100003840030198500000640002f9290007ac50203202f82902f929000002000344"},
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a40"},
-                       enb: "CONNECTED SHORT_MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD number_of_antenna_ports:AN1 prach_configuration:<root_sequence_index:15 zero_correlation_zone_configuration:7 high_speed_flag:true prach_frequency_offset:30 >  pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:<fdd:<ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75 > > eutra_mode:FDD ] []",
+                       enb: "CONNECTED SHORT_MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD  number_of_antenna_ports:AN1  prach_configuration:{root_sequence_index:15  zero_correlation_zone_configuration:7  high_speed_flag:true  prach_frequency_offset:30} pci:100  cell_id:\"02f929:0007ac50\"  tac:\"0203\"  broadcast_plmns:\"02f829\"  broadcast_plmns:\"02f929\"  choice_eutra_mode:{fdd:{ulear_fcn:2  dlear_fcn:3  ul_transmission_bandwidth:BW75  dl_transmission_bandwidth:BW75}}  eutra_mode:FDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -801,7 +802,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        */
                        packedPdu: "20060054000002001500090002f8298003007a4000140040010800630002f8290007ab50102002f829000001000133000100294001000037400500000f79e00000640002f9290007ac50203202f82902f929000002000344"},
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a08"},
-                       enb: "CONNECTED LONG_MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD prach_configuration:<root_sequence_index:15 zero_correlation_zone_configuration:7 high_speed_flag:true prach_frequency_offset:30 prach_configuration_index:60 >  pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:<fdd:<ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75 > > eutra_mode:FDD ] []",
+                       enb: "CONNECTED LONG_MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:{fdd:{ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50}} eutra_mode:FDD prach_configuration:{root_sequence_index:15 zero_correlation_zone_configuration:7 high_speed_flag:true prach_frequency_offset:30 prach_configuration_index:60} pci:100 cell_id:\"02f929:0007ac50\" tac:\"0203\" broadcast_plmns:\"02f829\" broadcast_plmns:\"02f929\" choice_eutra_mode:{fdd:{ulear_fcn:2 dlear_fcn:3 ul_transmission_bandwidth:BW75 dl_transmission_bandwidth:BW75}} eutra_mode:FDD] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -866,7 +867,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "20060050000002001500090002f829c003007a080014003c010800630002f8290007ab50102002f82900000100013300000037400640000f79ef000000640002f9290007ac50203202f82902f929000002000344"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD csg_id:\"0007aba0\" freq_band_indicator_priority:BROADCASTED bandwidth_reduced_si:SCHEDULED ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:{fdd:{ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50}} eutra_mode:FDD csg_id:\"0007aba0\" freq_band_indicator_priority:BROADCASTED bandwidth_reduced_si:SCHEDULED] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -917,7 +918,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "2006003e000002001500080002f82900007a800014002b000800630002f8290007ab50102002f8290000010001330002004640040007aba000a040014000b4400100"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD mbms_service_area_identities:\"02f8\" mbms_service_area_identities:\"03f9\" multiband_infos:1 multiband_infos:2 multiband_infos:3 freq_band_indicator_priority:NOT_BROADCASTED ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:{fdd:{ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50}} eutra_mode:FDD mbms_service_area_identities:\"02f8\" mbms_service_area_identities:\"03f9\" multiband_infos:1 multiband_infos:2 multiband_infos:3 freq_band_indicator_priority:NOT_BROADCASTED] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -975,7 +976,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        */
                        packedPdu: "20060044000002001500080002f82900007a8000140031000800630002f8290007ab50102002f8290000010001330002004f40050102f803f900a040010000544006200000010002"},
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD neighbour_infos:<ecgi:\"02f829:0007ab50\" pci:99 ear_fcn:1 > neighbour_infos:<ecgi:\"03f930:0008bc50\" pci:100 ear_fcn:2 > ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD  neighbour_infos:{ecgi:\"02f829:0007ab50\"  pci:99  ear_fcn:1}  neighbour_infos:{ecgi:\"03f930:0008bc50\"  pci:100  ear_fcn:2}] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -1026,7 +1027,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "20060044000002001500080002f82900007a8000140031004000630002f8290007ab50102002f82900000100013300020002f8290007ab50006300010003f9300008bc5000640002"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD neighbour_infos:<ecgi:\"02f829:0007ab50\" pci:99 ear_fcn:1 tac:\"0102\" > neighbour_infos:<ecgi:\"03f930:0008bc50\" pci:100 ear_fcn:3 > ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:{fdd:{ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50}} eutra_mode:FDD neighbour_infos:{ecgi:\"02f829:0007ab50\" pci:99 ear_fcn:1 tac:\"0102\"} neighbour_infos:{ecgi:\"03f930:0008bc50\" pci:100 ear_fcn:3}] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -1087,7 +1088,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                        packedPdu: "20060055000002001500080002f82900007a8000140042004000630002f8290007ab50102002f82900000100013300024002f8290007ab50006300010000004c400201024003f9300008bc50006400020000005e0003800103"},
 
                {key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "007a80"},
-                       enb: "CONNECTED MACRO_ENB [pci:99 cell_id:\"02f829:0007ab50\" tac:\"0102\" broadcast_plmns:\"02f829\" choice_eutra_mode:<fdd:<ulear_fcn:1 dlear_fcn:1 ul_transmission_bandwidth:BW50 dl_transmission_bandwidth:BW50 > > eutra_mode:FDD neighbour_infos:<ecgi:\"02f829:0007ab50\" pci:99 ear_fcn:1 tac:\"0102\" > neighbour_infos:<ecgi:\"03f930:0008bc50\" pci:100 ear_fcn:3 > ] []",
+                       enb: "CONNECTED MACRO_ENB [pci:99  cell_id:\"02f829:0007ab50\"  tac:\"0102\"  broadcast_plmns:\"02f829\"  choice_eutra_mode:{fdd:{ulear_fcn:1  dlear_fcn:1  ul_transmission_bandwidth:BW50  dl_transmission_bandwidth:BW50}}  eutra_mode:FDD  neighbour_infos:{ecgi:\"02f829:0007ab50\"  pci:99  ear_fcn:1  tac:\"0102\"}  neighbour_infos:{ecgi:\"03f930:0008bc50\"  pci:100  ear_fcn:3}] []",
                        /*
                                X2AP-PDU:
                                 successfulOutcome_t
@@ -1146,7 +1147,7 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                                           EARFCNExtension = 0x3
                        */
                        packedPdu: "20060055000002001500080002f82900007a8000140042004000630002f8290007ab50102002f82900000100013300024002f8290007ab50006300010000004c400201024003f9300008bc50006400020000005e0003800103",
-                       /*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),*/ },
+                       /*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)
@@ -1191,7 +1192,14 @@ func TestUnpackX2SetupResponseAndExtract(t *testing.T) {
                                nb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
                                nb.Configuration = &entities.NodebInfo_Enb{Enb: enb}
                                embStr := fmt.Sprintf("%s %s %s %s", nb.ConnectionStatus, enb.EnbType, enb.ServedCells, enb.GuGroupIds)
-                               if !strings.EqualFold(embStr, tc.enb) {
+
+                               space := regexp.MustCompile(`\s+`)
+                               s1 := space.ReplaceAllString(embStr, " ")
+                               s2 := space.ReplaceAllString(tc.enb," ")
+
+
+
+                               if !strings.EqualFold(s1, s2) {
                                        t.Errorf("want: enb=%s, got: %s", tc.enb, embStr)
                                }
                        }
index 0339b3c..3be5810 100644 (file)
@@ -1,13 +1,13 @@
 module e2mgr
 
 require (
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.35
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.35
-       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.35
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.42
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.42
+       gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.42
        gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.5.2
        github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
        github.com/go-ozzo/ozzo-validation v3.5.0+incompatible
-       github.com/golang/protobuf v1.3.4
+       github.com/golang/protobuf v1.4.2
        github.com/gorilla/mux v1.7.0
        github.com/magiconair/properties v1.8.1
        github.com/pelletier/go-toml v1.5.0 // indirect
@@ -23,7 +23,6 @@ require (
        google.golang.org/appengine v1.6.1 // indirect
        gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
        gopkg.in/yaml.v2 v2.2.8
-       k8s.io/apimachinery v0.17.0
        k8s.io/client-go v0.17.0
 )
 
index 4bb1c2a..5756914 100644 (file)
@@ -1,12 +1,12 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.35 h1:TGXHb4DNY8on+ej4S9VUnk2HibIC/5chDy64OE+bQBQ=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.35/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.35 h1:tkM3yE8UzmuH4nf9TqAmiNBSuIZ2CtcMRH2eBIYIzpQ=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.35/go.mod h1:G+4sUBMbLfQ+RrGS65U15tKmbnP+/1b5oLTPmMfyfT4=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.35 h1:LcxnUUDwsCzYEISKmkjkyYfg/lnLt8ofkPiGK69vNIA=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.35/go.mod h1:2bSaXTpECbZieB8bMnubTqMwF3n+mMBxlTaAXvcduNg=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.42 h1:k3Qpj1BiBPgu+HnMJl3TAi6MlcNwxgij3nY8Kw4NYW0=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.42/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.42 h1:EPdPmvU3iXgB4b91lNN8wl+WSpXCLi7gDm4yJTOrl/o=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.42/go.mod h1:YaQ+XEI4PcAoISxp9wUpUr2TP0J7JihpQTD0G1Lpd4A=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.42 h1:PyAnsgqXVV3w+1utUrtvh1KfxuVMCYvUXGYOFarChto=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.42/go.mod h1:K0P3Xh2NXHCwdIDY47IxeElCBVZdT4KqapPBpS7g3JU=
 gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2 h1:UK7awyRKIkVdokWvvkYvazlg3EWIfMnIqCcJxTnLlDA=
 gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
@@ -81,14 +81,23 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
 github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
-github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
 github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -305,6 +314,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -317,6 +328,13 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn
 google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/E2Manager/handlers/httpmsghandlers/set_general_configuration_handler.go b/E2Manager/handlers/httpmsghandlers/set_general_configuration_handler.go
new file mode 100644 (file)
index 0000000..851dab1
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package httpmsghandlers
+
+import "C"
+import (
+       "e2mgr/e2managererrors"
+       "e2mgr/logger"
+       "e2mgr/models"
+       "e2mgr/services"
+)
+
+type SetGeneralConfigurationHandler struct {
+       rnibDataService services.RNibDataService
+       logger          *logger.Logger
+}
+
+func NewSetGeneralConfigurationHandler(logger *logger.Logger, rnibDataService services.RNibDataService) *SetGeneralConfigurationHandler {
+       return &SetGeneralConfigurationHandler{
+               logger:          logger,
+               rnibDataService: rnibDataService,
+       }
+}
+
+func (h *SetGeneralConfigurationHandler) Handle(request models.Request) (models.IResponse, error) {
+       h.logger.Infof("#SetGeneralConfigurationHandler.Handle - handling set general parameters")
+
+       configuration := request.(models.GeneralConfigurationRequest)
+
+       existingConfig, err := h.rnibDataService.GetGeneralConfiguration()
+
+       if err != nil {
+               h.logger.Errorf("#SetGeneralConfigurationHandler.Handle - Error fetching general configuration from rNib: %s", err)
+               return nil, e2managererrors.NewRnibDbError()
+       }
+
+       if existingConfig.EnableRic != configuration.EnableRic {
+
+               existingConfig.EnableRic = configuration.EnableRic
+               err := h.rnibDataService.SaveGeneralConfiguration(existingConfig)
+
+               if err != nil {
+                       h.logger.Errorf("#SetGeneralConfigurationHandler.Handle - failed to save general configuration in RNIB. error: %s", err)
+                       return nil, e2managererrors.NewRnibDbError()
+               }
+
+       }
+       response := &models.GeneralConfigurationResponse{EnableRic: configuration.EnableRic}
+
+       return response, nil
+}
diff --git a/E2Manager/handlers/httpmsghandlers/set_general_configuration_handler_test.go b/E2Manager/handlers/httpmsghandlers/set_general_configuration_handler_test.go
new file mode 100644 (file)
index 0000000..284f922
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// 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.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+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"
+       "github.com/pkg/errors"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func setupSetGeneralConfigurationHandlerTest(t *testing.T) (*SetGeneralConfigurationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock) {
+       log := initLog(t)
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
+       handler := NewSetGeneralConfigurationHandler(log, rnibDataService)
+       return handler, readerMock, writerMock
+}
+
+func TestSetGeneralConfigurationFalse_Success(t *testing.T) {
+       handler, readerMock, writerMock := setupSetGeneralConfigurationHandlerTest(t)
+
+       configuration := &entities.GeneralConfiguration{EnableRic: true}
+       readerMock.On("GetGeneralConfiguration").Return(configuration, nil)
+
+       updated := &entities.GeneralConfiguration{EnableRic: false}
+       writerMock.On("SaveGeneralConfiguration", updated).Return(nil)
+
+       response, err := handler.Handle(models.GeneralConfigurationRequest{EnableRic: false})
+
+       assert.Nil(t, err)
+       assert.NotNil(t, response)
+       assert.IsType(t, &models.GeneralConfigurationResponse{}, response)
+}
+
+func TestSetGeneralConfigurationTrue_Success(t *testing.T) {
+       handler, readerMock, writerMock := setupSetGeneralConfigurationHandlerTest(t)
+
+       configuration := &entities.GeneralConfiguration{EnableRic: false}
+       readerMock.On("GetGeneralConfiguration").Return(configuration, nil)
+
+       updated := &entities.GeneralConfiguration{EnableRic: true}
+       writerMock.On("SaveGeneralConfiguration", updated).Return(nil)
+
+       response, err := handler.Handle(models.GeneralConfigurationRequest{EnableRic: true})
+
+       assert.Nil(t, err)
+       assert.NotNil(t, response)
+       assert.IsType(t, &models.GeneralConfigurationResponse{}, response)
+}
+
+func TestSetGeneralConfigurationIgnore_Success(t *testing.T) {
+       handler, readerMock, _ := setupSetGeneralConfigurationHandlerTest(t)
+
+       configuration := &entities.GeneralConfiguration{EnableRic: false}
+       readerMock.On("GetGeneralConfiguration").Return(configuration, nil)
+
+       response, err := handler.Handle(models.GeneralConfigurationRequest{EnableRic: false})
+
+       assert.Nil(t, err)
+       assert.NotNil(t, response)
+       assert.IsType(t, &models.GeneralConfigurationResponse{}, response)
+}
+
+func TestSetGeneralConfigurationHandlerRnibError(t *testing.T) {
+       handler, readerMock, writerMock := setupSetGeneralConfigurationHandlerTest(t)
+
+       configuration := &entities.GeneralConfiguration{EnableRic: false}
+       readerMock.On("GetGeneralConfiguration").Return(configuration, nil)
+
+       updated := &entities.GeneralConfiguration{EnableRic: true}
+       writerMock.On("SaveGeneralConfiguration", updated).Return(common.NewInternalError(errors.New("error")))
+
+       response, err := handler.Handle(models.GeneralConfigurationRequest{EnableRic: true})
+
+       assert.NotNil(t, err)
+       assert.Nil(t, response)
+}
index 7cd5458..7420a29 100644 (file)
@@ -38,6 +38,11 @@ import (
        "strings"
 )
 
+var (
+       emptyTagsToReplaceToSelfClosingTags = []string{"reject", "ignore", "transport-resource-unavailable", "om-intervention",
+               "v60s", "v20s", "v10s", "v5s", "v2s", "v1s"}
+)
+
 type E2SetupRequestNotificationHandler struct {
        logger                *logger.Logger
        config                *configuration.Configuration
@@ -47,8 +52,8 @@ type E2SetupRequestNotificationHandler struct {
        e2tAssociationManager *managers.E2TAssociationManager
 }
 
-func NewE2SetupRequestNotificationHandler(logger *logger.Logger, config *configuration.Configuration, e2tInstancesManager managers.IE2TInstancesManager, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService, e2tAssociationManager *managers.E2TAssociationManager) E2SetupRequestNotificationHandler {
-       return E2SetupRequestNotificationHandler{
+func NewE2SetupRequestNotificationHandler(logger *logger.Logger, config *configuration.Configuration, e2tInstancesManager managers.IE2TInstancesManager, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService, e2tAssociationManager *managers.E2TAssociationManager) *E2SetupRequestNotificationHandler {
+       return &E2SetupRequestNotificationHandler{
                logger:                logger,
                config:                config,
                e2tInstancesManager:   e2tInstancesManager,
@@ -58,10 +63,23 @@ func NewE2SetupRequestNotificationHandler(logger *logger.Logger, config *configu
        }
 }
 
-func (h E2SetupRequestNotificationHandler) Handle(request *models.NotificationRequest) {
+func (h *E2SetupRequestNotificationHandler) Handle(request *models.NotificationRequest) {
        ranName := request.RanName
        h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - received E2_SETUP_REQUEST. Payload: %x", ranName, request.Payload)
 
+       generalConfiguration, err := h.rNibDataService.GetGeneralConfiguration()
+
+       if err != nil {
+               h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - Failed retrieving e2m general configuration. error: %s", err)
+               return
+       }
+
+       if !generalConfiguration.EnableRic {
+               cause := models.Cause{Misc: &models.CauseMisc{OmIntervention: &struct{}{}}}
+               h.handleUnsuccessfulResponse(ranName, request, cause)
+               return
+       }
+
        setupRequest, e2tIpAddress, err := h.parseSetupRequest(request.Payload)
        if err != nil {
                h.logger.Errorf(err.Error())
@@ -104,7 +122,8 @@ func (h E2SetupRequestNotificationHandler) Handle(request *models.NotificationRe
 
                h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to associate E2T to nodeB entity. Error: %s", ranName, err)
                if _, ok := err.(*e2managererrors.RoutingManagerError); ok {
-                       h.handleUnsuccessfulResponse(nodebInfo, request)
+                       cause := models.Cause{Transport: &models.CauseTransport{TransportResourceUnavailable: &struct{}{}}}
+                       h.handleUnsuccessfulResponse(nodebInfo.RanName, request, cause)
                }
                return
        }
@@ -112,7 +131,7 @@ func (h E2SetupRequestNotificationHandler) Handle(request *models.NotificationRe
        h.handleSuccessfulResponse(ranName, request, setupRequest)
 }
 
-func (h E2SetupRequestNotificationHandler) handleNewRan(ranName string, e2tIpAddress string, setupRequest *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
+func (h *E2SetupRequestNotificationHandler) handleNewRan(ranName string, e2tIpAddress string, setupRequest *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
 
        nodebInfo, err := h.buildNodebInfo(ranName, e2tIpAddress, setupRequest)
 
@@ -132,13 +151,8 @@ func (h E2SetupRequestNotificationHandler) handleNewRan(ranName string, e2tIpAdd
        return nodebInfo, nil
 }
 
-func (h E2SetupRequestNotificationHandler) setGnbFunctions(nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
-       ranFunctions, err := setupRequest.ExtractRanFunctionsList()
-
-       if err != nil {
-               h.logger.Errorf("#E2SetupRequestNotificationHandler.setGnbFunctions - RAN name: %s - failed to update nodebInfo entity. Error: %s", nodebInfo.GetRanName(), err)
-               return err
-       }
+func (h *E2SetupRequestNotificationHandler) setGnbFunctions(nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
+       ranFunctions := setupRequest.ExtractRanFunctionsList()
 
        if ranFunctions != nil {
                nodebInfo.GetGnb().RanFunctions = ranFunctions
@@ -147,7 +161,7 @@ func (h E2SetupRequestNotificationHandler) setGnbFunctions(nodebInfo *entities.N
        return nil
 }
 
-func (h E2SetupRequestNotificationHandler) handleExistingRan(ranName string, nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
+func (h *E2SetupRequestNotificationHandler) handleExistingRan(ranName string, nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
        if nodebInfo.GetConnectionStatus() == entities.ConnectionStatus_SHUTTING_DOWN {
                h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", ranName, nodebInfo.ConnectionStatus)
                return errors.New("nodeB entity in incorrect state")
@@ -157,31 +171,33 @@ func (h E2SetupRequestNotificationHandler) handleExistingRan(ranName string, nod
        return err
 }
 
-func (h E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(nodebInfo *entities.NodebInfo, req *models.NotificationRequest) {
-       failureResponse := models.NewE2SetupFailureResponseMessage(models.TimeToWaitEnum.V60s)
+func (h *E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(ranName string, req *models.NotificationRequest, cause models.Cause) {
+       failureResponse := models.NewE2SetupFailureResponseMessage(models.TimeToWaitEnum.V60s, cause)
        h.logger.Debugf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", failureResponse)
 
        responsePayload, err := xml.Marshal(&failureResponse.E2APPDU)
        if err != nil {
-               h.logger.Warnf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", nodebInfo.RanName, responsePayload)
+               h.logger.Warnf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
        }
 
        responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
 
-       msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_FAILURE, nodebInfo.RanName, responsePayload, req.TransactionId, req.GetMsgSrc())
-       h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", nodebInfo.RanName, msg)
+       h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - payload: %s", responsePayload)
+       msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_FAILURE, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
+       h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
        _ = h.rmrSender.WhSend(msg)
 
 }
 
-func (h E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName string, req *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage) {
+func (h *E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName string, req *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage) {
+
+       plmnId := buildPlmnId(h.config.GlobalRicId.Mcc, h.config.GlobalRicId.Mnc)
 
-       ricNearRtId, err := convertTo20BitString(h.config.GlobalRicId.RicNearRtId)
+       ricNearRtId, err := convertTo20BitString(h.config.GlobalRicId.RicId)
        if err != nil {
-               h.logger.Errorf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - failed to convert RicNearRtId value %s to 20 bit string . Error: %s", ranName, h.config.GlobalRicId.RicNearRtId, err)
                return
        }
-       successResponse := models.NewE2SetupSuccessResponseMessage(h.config.GlobalRicId.PlmnId, ricNearRtId, setupRequest)
+       successResponse := models.NewE2SetupSuccessResponseMessage(plmnId, ricNearRtId, setupRequest)
        h.logger.Debugf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", successResponse)
 
        responsePayload, err := xml.Marshal(&successResponse.E2APPDU)
@@ -191,23 +207,42 @@ func (h E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName stri
 
        responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
 
+       h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - payload: %s", responsePayload)
+
        msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_RESP, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
        h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
        _ = h.rmrSender.Send(msg)
 }
 
+func buildPlmnId(mmc string, mnc string) string {
+       var b strings.Builder
+
+       b.WriteByte(mmc[1])
+       b.WriteByte(mmc[0])
+       if len(mnc) == 2 {
+               b.WriteString("F")
+       } else {
+               b.WriteByte(mnc[2])
+       }
+       b.WriteByte(mmc[2])
+       b.WriteByte(mnc[1])
+       b.WriteByte(mnc[0])
+
+       return b.String()
+}
+
 func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte {
-       responseString := strings.NewReplacer(
-               "<reject></reject>", "<reject/>",
-               "<ignore></ignore>", "<ignore/>",
-               "<transport-resource-unavailable></transport-resource-unavailable>", "<transport-resource-unavailable/>",
-               "<v60s></v60s>", "<v60s/>",
-               "<v20s></v20s>", "<v20s/>",
-               "<v10s></v10s>", "<v10s/>",
-               "<v5s></v5s>", "<v5s/>",
-               "<v2s></v2s>", "<v2s/>",
-               "<v1s></v1s>", "<v1s/>",
-       ).Replace(string(responsePayload))
+
+       emptyTagVsSelfClosingTagPairs := make([]string, len(emptyTagsToReplaceToSelfClosingTags)*2)
+
+       j := 0
+
+       for i := 0; i < len(emptyTagsToReplaceToSelfClosingTags); i++ {
+               emptyTagVsSelfClosingTagPairs[j] = fmt.Sprintf("<%[1]s></%[1]s>", emptyTagsToReplaceToSelfClosingTags[i])
+               emptyTagVsSelfClosingTagPairs[j+1] = fmt.Sprintf("<%s/>", emptyTagsToReplaceToSelfClosingTags[i])
+               j += 2
+       }
+       responseString := strings.NewReplacer(emptyTagVsSelfClosingTagPairs...).Replace(string(responsePayload))
        return []byte(responseString)
 }
 
@@ -219,7 +254,7 @@ func convertTo20BitString(ricNearRtId string) (string, error) {
        return fmt.Sprintf("%020b", r)[:20], nil
 }
 
-func (h E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*models.E2SetupRequestMessage, string, error) {
+func (h *E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*models.E2SetupRequestMessage, string, error) {
 
        pipInd := bytes.IndexByte(payload, '|')
        if pipInd < 0 {
@@ -234,7 +269,7 @@ func (h E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*m
        h.logger.Infof("#E2SetupRequestNotificationHandler.parseSetupRequest - payload: %s", payload[pipInd+1:])
 
        setupRequest := &models.E2SetupRequestMessage{}
-       err := xml.Unmarshal(payload[pipInd+1:], &setupRequest.E2APPDU)
+       err := xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
        if err != nil {
                return nil, "", errors.New(fmt.Sprintf("#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: %x", payload))
        }
@@ -242,6 +277,12 @@ func (h E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*m
        return setupRequest, e2tIpAddress, nil
 }
 
+func normalizeXml(payload []byte) []byte {
+       xmlStr := string(payload)
+       normalized := strings.NewReplacer("&lt;", "<", "&gt;", ">").Replace(xmlStr)
+       return []byte(normalized)
+}
+
 func (h E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAddress string, request *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
 
        var err error
@@ -251,7 +292,7 @@ func (h E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAdd
                RanName:                      ranName,
                NodeType:                     entities.Node_GNB,
                Configuration:                &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{}},
-               GlobalNbId: h.buildGlobalNbId(request),
+               GlobalNbId:                   h.buildGlobalNbId(request),
        }
 
        err = h.setGnbFunctions(nodebInfo, request)
@@ -268,6 +309,6 @@ func (h E2SetupRequestNotificationHandler) buildGlobalNbId(setupRequest *models.
 func (h E2SetupRequestNotificationHandler) buildNbIdentity(ranName string, setupRequest *models.E2SetupRequestMessage) *entities.NbIdentity {
        return &entities.NbIdentity{
                InventoryName: ranName,
-               GlobalNbId: h.buildGlobalNbId(setupRequest),
+               GlobalNbId:    h.buildGlobalNbId(setupRequest),
        }
 }
index 28dfe76..41ddcca 100644 (file)
@@ -20,6 +20,7 @@
 package rmrmsghandlers
 
 import (
+       "bytes"
        "e2mgr/configuration"
        "e2mgr/managers"
        "e2mgr/mocks"
@@ -27,9 +28,11 @@ import (
        "e2mgr/rmrCgo"
        "e2mgr/services"
        "e2mgr/tests"
+       "encoding/xml"
        "errors"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/golang/protobuf/ptypes/wrappers"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
        "io/ioutil"
@@ -38,14 +41,16 @@ import (
 )
 
 const (
-       prefix                   = "10.0.2.15:9999|"
-       e2tInstanceFullAddress   = "10.0.2.15:9999"
-       nodebRanName             = "gnb:310-410-b5c67788"
-       GnbSetupRequestXmlPath   = "../../tests/resources/setupRequest_gnb.xml"
-       GnbWithoutFunctionsSetupRequestXmlPath   = "../../tests/resources/setupRequest_gnb_without_functions.xml"
-       EnGnbSetupRequestXmlPath = "../../tests/resources/setupRequest_en-gNB.xml"
-       NgEnbSetupRequestXmlPath = "../../tests/resources/setupRequest_ng-eNB.xml"
-       EnbSetupRequestXmlPath   = "../../tests/resources/setupRequest_enb.xml"
+       prefix                                 = "10.0.2.15:9999|"
+       e2tInstanceFullAddress                 = "10.0.2.15:9999"
+       nodebRanName                           = "gnb:310-410-b5c67788"
+       GnbSetupRequestXmlPath                 = "../../tests/resources/setupRequest_gnb.xml"
+       EnGnbSetupRequestXmlPath               = "../../tests/resources/setupRequest_en-gNB.xml"
+       NgEnbSetupRequestXmlPath               = "../../tests/resources/setupRequest_ng-eNB.xml"
+       EnbSetupRequestXmlPath                 = "../../tests/resources/setupRequest_enb.xml"
+       GnbWithoutFunctionsSetupRequestXmlPath = "../../tests/resources/setupRequest_gnb_without_functions.xml"
+       E2SetupFailureResponseWithMiscCause    = "<E2AP-PDU><unsuccessfulOutcome><procedureCode>1</procedureCode><criticality><reject/></criticality><value><E2setupFailure><protocolIEs><E2setupFailureIEs><id>1</id><criticality><ignore/></criticality><value><Cause><misc><om-intervention/></misc></Cause></value></E2setupFailureIEs><E2setupFailureIEs><id>31</id><criticality><ignore/></criticality><value><TimeToWait><v60s/></TimeToWait></value></E2setupFailureIEs></protocolIEs></E2setupFailure></value></unsuccessfulOutcome></E2AP-PDU>"
+       E2SetupFailureResponseWithTransportCause = "<E2AP-PDU><unsuccessfulOutcome><procedureCode>1</procedureCode><criticality><reject/></criticality><value><E2setupFailure><protocolIEs><E2setupFailureIEs><id>1</id><criticality><ignore/></criticality><value><Cause><transport><transport-resource-unavailable/></transport></Cause></value></E2setupFailureIEs><E2setupFailureIEs><id>31</id><criticality><ignore/></criticality><value><TimeToWait><v60s/></TimeToWait></value></E2setupFailureIEs></protocolIEs></E2setupFailure></value></unsuccessfulOutcome></E2AP-PDU>"
 )
 
 func readXmlFile(t *testing.T, xmlPath string) []byte {
@@ -66,8 +71,8 @@ func TestParseGnbSetupRequest_Success(t *testing.T) {
        handler, _, _, _, _, _ := initMocks(t)
        prefBytes := []byte(prefix)
        request, _, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...))
-       assert.Equal(t, "131014", request.GetPlmnId())
-       assert.Equal(t, "10011001101010101011", request.GetNbId())
+       assert.Equal(t, "02F829", request.GetPlmnId())
+       assert.Equal(t, "001100000011000000110000", request.GetNbId())
        assert.Nil(t, err)
 }
 
@@ -120,51 +125,85 @@ func TestParseSetupRequest_UnmarshalFailure(t *testing.T) {
        assert.EqualError(t, err, "#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: 31302e302e322e31353a393939397c010203")
 }
 
+func TestE2SetupRequestNotificationHandler_GetGeneralConfigurationFailure(t *testing.T) {
+       xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
+       handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{}, common.NewInternalError(errors.New("some error")))
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), xmlGnb...)}
+       handler.Handle(notificationRequest)
+       rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+       e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance")
+       routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance")
+       readerMock.AssertNotCalled(t, "GetNodeb")
+       writerMock.AssertNotCalled(t, "SaveNodeb")
+}
+
+func getMbuf(msgType int, payloadStr string, request *models.NotificationRequest) *rmrCgo.MBuf {
+       payload := []byte(payloadStr)
+       mbuf := rmrCgo.NewMBuf(msgType, len(payload), nodebRanName,&payload,&request.TransactionId, request.GetMsgSrc() )
+       return mbuf
+}
+
+func TestE2SetupRequestNotificationHandler_EnableRicFalse(t *testing.T) {
+       xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
+       handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: false}, nil)
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), xmlGnb...)}
+       mbuf := getMbuf(rmrCgo.RIC_E2_SETUP_FAILURE, E2SetupFailureResponseWithMiscCause, notificationRequest)
+       rmrMessengerMock.On("WhSendMsg", mbuf, true).Return(&rmrCgo.MBuf{}, nil)
+       handler.Handle(notificationRequest)
+       rmrMessengerMock.AssertCalled(t, "WhSendMsg", mbuf,true )
+       e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance")
+       routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance")
+       readerMock.AssertNotCalled(t, "GetNodeb")
+       writerMock.AssertNotCalled(t, "SaveNodeb")
+}
+
 func TestE2SetupRequestNotificationHandler_HandleNewGnbSuccess(t *testing.T) {
        xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        var gnb *entities.NodebInfo
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
-       writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), xmlGnb...)}
+       nodebInfo := getExpectedNodebWithFunctionsForNewRan(notificationRequest.Payload)
+       writerMock.On("SaveNodeb", mock.Anything, nodebInfo).Return(nil)
        routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
        writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
        e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
-       var errEmpty error
-       rmrMessage := &rmrCgo.MBuf{}
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
-       prefBytes := []byte(prefix)
-       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
+       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(&rmrCgo.MBuf{}, nil)
        handler.Handle(notificationRequest)
+       writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
        assertNewNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
 }
 
 func TestE2SetupRequestNotificationHandler_HandleNewGnbWithoutFunctionsSuccess(t *testing.T) {
        xmlGnb := readXmlFile(t, GnbWithoutFunctionsSetupRequestXmlPath)
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        var gnb *entities.NodebInfo
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
-       writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), xmlGnb...)}
+       nodebInfo := getExpectedNodebWithFunctionsForNewRan(notificationRequest.Payload)
+       writerMock.On("SaveNodeb", mock.Anything, nodebInfo).Return(nil)
        routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
        writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
        e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
        var errEmpty error
        rmrMessage := &rmrCgo.MBuf{}
        rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
-       prefBytes := []byte(prefix)
-       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
        handler.Handle(notificationRequest)
+       writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
        assertNewNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
 }
 
 func TestE2SetupRequestNotificationHandler_HandleNewEnGnbSuccess(t *testing.T) {
        xmlEnGnb := readXmlFile(t, EnGnbSetupRequestXmlPath)
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        var gnb *entities.NodebInfo
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
        writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
@@ -183,8 +222,8 @@ func TestE2SetupRequestNotificationHandler_HandleNewEnGnbSuccess(t *testing.T) {
 func TestE2SetupRequestNotificationHandler_HandleNewNgEnbSuccess(t *testing.T) {
        xmlNgEnb := readXmlFile(t, NgEnbSetupRequestXmlPath)
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        var gnb *entities.NodebInfo
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
        writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
@@ -204,8 +243,8 @@ func TestE2SetupRequestNotificationHandler_HandleExistingGnbSuccess(t *testing.T
        xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
 
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        var gnb = &entities.NodebInfo{
                RanName:                      nodebRanName,
                AssociatedE2TInstanceAddress: e2tInstanceFullAddress,
@@ -215,23 +254,88 @@ func TestE2SetupRequestNotificationHandler_HandleExistingGnbSuccess(t *testing.T
        }
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, nil)
        routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
-       writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
+
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), xmlGnb...)}
+       gnbToUpdate := getExpectedNodebWithFunctionsForExistingRan(*gnb, notificationRequest.Payload)
+       writerMock.On("UpdateNodebInfo", gnbToUpdate).Return(nil)
        e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
        var errEmpty error
-       rmrMessage := &rmrCgo.MBuf{}
-       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
-       prefBytes := []byte(prefix)
-       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
+       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(&rmrCgo.MBuf{}, errEmpty)
        handler.Handle(notificationRequest)
+       writerMock.AssertCalled(t, "UpdateNodebInfo", gnbToUpdate)
        assertExistingNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
 }
 
-func TestE2SetupRequestNotificationHandler_HandleParseError(t *testing.T) {
+func TestE2SetupRequestNotificationHandler_HandleExistingGnbWithFunctionsSuccess(t *testing.T) {
        xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
 
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       prefBytes := []byte("invalid_prefix")
-       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
+       var gnb = &entities.NodebInfo{
+               RanName:                      nodebRanName,
+               AssociatedE2TInstanceAddress: e2tInstanceFullAddress,
+               ConnectionStatus:             entities.ConnectionStatus_CONNECTED,
+               NodeType:                     entities.Node_GNB,
+               Configuration: &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{RanFunctions: []*entities.RanFunction{
+                       {
+                               RanFunctionId:       &wrappers.UInt32Value{Value: 2},
+                               RanFunctionRevision: &wrappers.UInt32Value{Value: 2},
+                       },
+               }}},
+       }
+       readerMock.On("GetNodeb", mock.Anything).Return(gnb, nil)
+       routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(nil)
+
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), xmlGnb...)}
+       gnbToUpdate := getExpectedNodebWithFunctionsForExistingRan(*gnb, notificationRequest.Payload)
+
+       writerMock.On("UpdateNodebInfo", gnbToUpdate).Return(nil)
+       e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
+       var errEmpty error
+       rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(&rmrCgo.MBuf{}, errEmpty)
+       handler.Handle(notificationRequest)
+       writerMock.AssertCalled(t, "UpdateNodebInfo", gnbToUpdate)
+       assertExistingNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
+}
+
+func getExpectedNodebWithFunctionsForExistingRan(nodeb entities.NodebInfo, payload []byte) *entities.NodebInfo {
+       pipInd := bytes.IndexByte(payload, '|')
+       setupRequest := &models.E2SetupRequestMessage{}
+       _ = xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
+       nodeb.GetGnb().RanFunctions = setupRequest.ExtractRanFunctionsList()
+       return &nodeb
+}
+
+func getExpectedNodebWithFunctionsForNewRan(payload []byte) *entities.NodebInfo {
+       pipInd := bytes.IndexByte(payload, '|')
+       setupRequest := &models.E2SetupRequestMessage{}
+       _ = xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
+
+       nodeb := &entities.NodebInfo{
+               AssociatedE2TInstanceAddress: e2tInstanceFullAddress,
+               ConnectionStatus:             entities.ConnectionStatus_CONNECTED,
+               RanName:                      nodebRanName,
+               NodeType:                     entities.Node_GNB,
+               Configuration: &entities.NodebInfo_Gnb{
+                       Gnb: &entities.Gnb{
+                               RanFunctions: setupRequest.ExtractRanFunctionsList(),
+                       },
+               },
+               GlobalNbId: &entities.GlobalNbId{
+                       PlmnId: setupRequest.GetPlmnId(),
+                       NbId:   setupRequest.GetNbId(),
+               },
+       }
+
+       return nodeb
+}
+
+func TestE2SetupRequestNotificationHandler_HandleParseError(t *testing.T) {
+       xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
+       handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte("invalid_prefix"), xmlGnb...)}
        handler.Handle(notificationRequest)
        readerMock.AssertNotCalled(t, "GetNodeb", mock.Anything)
        writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
@@ -243,8 +347,8 @@ func TestE2SetupRequestNotificationHandler_HandleParseError(t *testing.T) {
 
 func TestE2SetupRequestNotificationHandler_HandleUnmarshalError(t *testing.T) {
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       prefBytes := []byte(prefix)
-       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, "xmlGnb"...)}
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), "xmlGnb"...)}
        handler.Handle(notificationRequest)
        readerMock.AssertNotCalled(t, "GetNodeb", mock.Anything)
        writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
@@ -257,8 +361,8 @@ func TestE2SetupRequestNotificationHandler_HandleUnmarshalError(t *testing.T) {
 func TestE2SetupRequestNotificationHandler_HandleGetE2TInstanceError(t *testing.T) {
        xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       var e2tInstance *entities.E2TInstance
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, common.NewResourceNotFoundError("Not found"))
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, common.NewResourceNotFoundError("Not found"))
        prefBytes := []byte(prefix)
        notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
        handler.Handle(notificationRequest)
@@ -273,14 +377,12 @@ func TestE2SetupRequestNotificationHandler_HandleGetE2TInstanceError(t *testing.
 
 func TestE2SetupRequestNotificationHandler_HandleGetNodebError(t *testing.T) {
        xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
-
        handler, readerMock, writerMock, routingManagerClientMock, e2tInstancesManagerMock, rmrMessengerMock := initMocks(t)
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        var gnb *entities.NodebInfo
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewInternalError(errors.New("some error")))
-       prefBytes := []byte(prefix)
-       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), xmlGnb...)}
        handler.Handle(notificationRequest)
        e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
        readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
@@ -295,8 +397,8 @@ func TestE2SetupRequestNotificationHandler_HandleAssociationError(t *testing.T)
        xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
 
        handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock := initMocks(t)
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        var gnb *entities.NodebInfo
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
        writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
@@ -304,11 +406,9 @@ func TestE2SetupRequestNotificationHandler_HandleAssociationError(t *testing.T)
        e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
        routingManagerClientMock.On("AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything).Return(errors.New("association error"))
        var errEmpty error
-       rmrMessage := &rmrCgo.MBuf{}
-       rmrMessengerMock.On("WhSendMsg", mock.Anything, mock.Anything).Return(rmrMessage, errEmpty)
-
-       prefBytes := []byte(prefix)
-       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
+       notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append([]byte(prefix), xmlGnb...)}
+       mbuf := getMbuf(rmrCgo.RIC_E2_SETUP_FAILURE, E2SetupFailureResponseWithTransportCause, notificationRequest)
+       rmrMessengerMock.On("WhSendMsg", mbuf, true).Return(&rmrCgo.MBuf{}, errEmpty)
        handler.Handle(notificationRequest)
        readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
        e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
@@ -316,16 +416,17 @@ func TestE2SetupRequestNotificationHandler_HandleAssociationError(t *testing.T)
        routingManagerClientMock.AssertCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
        writerMock.AssertCalled(t, "UpdateNodebInfo", mock.Anything)
        e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
-       rmrMessengerMock.AssertCalled(t, "WhSendMsg", mock.Anything, mock.Anything)
+       rmrMessengerMock.AssertCalled(t, "WhSendMsg", mbuf, true)
 }
 
 func TestE2SetupRequestNotificationHandler_ConvertTo20BitStringError(t *testing.T) {
        xmlEnGnb := readXmlFile(t, EnGnbSetupRequestXmlPath)
        logger := tests.InitLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, GlobalRicId: struct {
-               PlmnId      string
-               RicNearRtId string
-       }{PlmnId: "131014", RicNearRtId: "10011001101010101011"}}
+               RicId string
+               Mcc   string
+               Mnc   string
+       }{Mcc: "327", Mnc: "94", RicId: "10011001101010101011"}}
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
        readerMock := &mocks.RnibReaderMock{}
@@ -335,9 +436,8 @@ func TestE2SetupRequestNotificationHandler_ConvertTo20BitStringError(t *testing.
        e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
        e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock)
        handler := NewE2SetupRequestNotificationHandler(logger, config, e2tInstancesManagerMock, rmrSender, rnibDataService, e2tAssociationManager)
-
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        var gnb *entities.NodebInfo
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
        writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
@@ -364,8 +464,8 @@ func TestE2SetupRequestNotificationHandler_HandleExistingGnbInvalidStatusError(t
        handler, readerMock, writerMock, routingManagerClientMock, e2tInstancesManagerMock, rmrMessengerMock := initMocks(t)
        var gnb = &entities.NodebInfo{RanName: nodebRanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}
        readerMock.On("GetNodeb", mock.Anything).Return(gnb, nil)
-       var e2tInstance = &entities.E2TInstance{}
-       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(e2tInstance, nil)
+       readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil)
+       e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil)
        prefBytes := []byte(prefix)
        notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
        handler.Handle(notificationRequest)
@@ -378,12 +478,13 @@ func TestE2SetupRequestNotificationHandler_HandleExistingGnbInvalidStatusError(t
        rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
 }
 
-func initMocks(t *testing.T) (E2SetupRequestNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) {
+func initMocks(t *testing.T) (*E2SetupRequestNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) {
        logger := tests.InitLog(t)
        config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, GlobalRicId: struct {
-               PlmnId      string
-               RicNearRtId string
-       }{PlmnId: "131014", RicNearRtId: "556670"}}
+               RicId string
+               Mcc   string
+               Mnc   string
+       }{Mcc: "327", Mnc: "94", RicId: "AACCE"}}
        rmrMessengerMock := &mocks.RmrMessengerMock{}
        rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
        readerMock := &mocks.RnibReaderMock{}
index 85255eb..1da8758 100644 (file)
@@ -38,6 +38,8 @@ import (
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
+const ResetRequesLogInfoElapsedTime = "#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms"
+
 type X2ResetRequestNotificationHandler struct {
        logger                 *logger.Logger
        rnibDataService        services.RNibDataService
@@ -61,7 +63,7 @@ func (h X2ResetRequestNotificationHandler) Handle(request *models.NotificationRe
        nb, rNibErr := h.rnibDataService.GetNodeb(request.RanName)
        if rNibErr != nil {
                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))
+               h.logger.Infof(ResetRequesLogInfoElapsedTime, utils.ElapsedTime(request.StartTime))
                return
        }
 
@@ -69,19 +71,19 @@ func (h X2ResetRequestNotificationHandler) Handle(request *models.NotificationRe
 
        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))
+               h.logger.Infof(ResetRequesLogInfoElapsedTime, utils.ElapsedTime(request.StartTime))
                return
        }
 
        if nb.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
                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))
+               h.logger.Infof(ResetRequesLogInfoElapsedTime, utils.ElapsedTime(request.StartTime))
                return
        }
 
        msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET_RESP, request.RanName, e2pdus.PackedX2ResetResponse, request.TransactionId, request.GetMsgSrc())
 
        _ = 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.logger.Infof(ResetRequesLogInfoElapsedTime, utils.ElapsedTime(request.StartTime))
        _ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_RESTARTED, enums.RAN_TO_RIC, nb)
 }
index 1097ed2..ca1b175 100644 (file)
@@ -36,6 +36,8 @@ import (
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
 )
 
+const ResetResponseLogInfoElapsedTime = "#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms"
+
 type X2ResetResponseHandler struct {
        logger                 *logger.Logger
        rnibDataService        services.RNibDataService
@@ -64,19 +66,19 @@ func (h X2ResetResponseHandler) Handle(request *models.NotificationRequest) {
 
        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))
+               h.logger.Infof(ResetResponseLogInfoElapsedTime, 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))
+               h.logger.Infof(ResetResponseLogInfoElapsedTime, 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))
+       h.logger.Infof(ResetResponseLogInfoElapsedTime, utils.ElapsedTime(request.StartTime))
 
        if err != nil || !isSuccessfulResetResponse {
                return
index a022ecb..320acd0 100644 (file)
@@ -49,6 +49,7 @@ func initializeRoutes(router *mux.Router, rootController controllers.IRootContro
        rr.HandleFunc("/{ranName}", nodebController.GetNodeb).Methods(http.MethodGet)
        rr.HandleFunc("/{ranName}/update", nodebController.UpdateGnb).Methods(http.MethodPut)
        rr.HandleFunc("/shutdown", nodebController.Shutdown).Methods(http.MethodPut)
+       rr.HandleFunc("/parameters", nodebController.SetGeneralConfiguration).Methods(http.MethodPut)
        rrr := r.PathPrefix("/e2t").Subrouter()
        rrr.HandleFunc("/list", e2tController.GetE2TInstances).Methods(http.MethodGet)
 }
index 3c0620b..cdca134 100644 (file)
@@ -39,6 +39,7 @@ func setupRouterAndMocks() (*mux.Router, *mocks.RootControllerMock, *mocks.Nodeb
        nodebControllerMock.On("Shutdown").Return(nil)
        nodebControllerMock.On("GetNodeb").Return(nil)
        nodebControllerMock.On("GetNodebIdList").Return(nil)
+       nodebControllerMock.On("SetGeneralConfiguration").Return(nil)
 
        e2tControllerMock := &mocks.E2TControllerMock{}
 
@@ -103,6 +104,19 @@ func TestRoutePutNodebShutdown(t *testing.T) {
        nodebControllerMock.AssertNumberOfCalls(t, "Shutdown", 1)
 }
 
+func TestRoutePutNodebSetGeneralConfiguration(t *testing.T) {
+       router, _, nodebControllerMock, _ := setupRouterAndMocks()
+
+       req, err := http.NewRequest("PUT", "/v1/nodeb/parameters", nil)
+       if err != nil {
+               t.Fatal(err)
+       }
+       rr := httptest.NewRecorder()
+       router.ServeHTTP(rr, req)
+
+       nodebControllerMock.AssertNumberOfCalls(t, "SetGeneralConfiguration", 1)
+}
+
 func TestRouteNotFound(t *testing.T) {
        router, _, _,_ := setupRouterAndMocks()
 
diff --git a/E2Manager/managers/ran_connect_status_change_manager.go b/E2Manager/managers/ran_connect_status_change_manager.go
new file mode 100644 (file)
index 0000000..26d12b2
--- /dev/null
@@ -0,0 +1,131 @@
+//
+// 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.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package managers
+
+import (
+       "e2mgr/logger"
+       "e2mgr/services"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+)
+
+const (
+       CONNECTED_RAW_EVENT    = "CONNECTED"
+       DISCONNECTED_RAW_EVENT = "DISCONNECTED"
+       NONE_RAW_EVENT         = "NONE"
+)
+
+type RanConnectStatusChangeManager struct {
+       logger          *logger.Logger
+       rnibDataService services.RNibDataService
+       ranListManager  RanListManager
+       ranAlarmService services.RanAlarmService
+}
+
+func NewRanConnectStatusChangeManager(logger *logger.Logger, rnibDataService services.RNibDataService, ranListManager RanListManager, ranAlarmService services.RanAlarmService) *RanConnectStatusChangeManager {
+       return &RanConnectStatusChangeManager{
+               logger:          logger,
+               rnibDataService: rnibDataService,
+               ranListManager:  ranListManager,
+               ranAlarmService: ranAlarmService,
+       }
+}
+
+func (m *RanConnectStatusChangeManager) ChangeStatus(nodebInfo *entities.NodebInfo, nextStatus entities.ConnectionStatus) error {
+       m.logger.Infof("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s, currentStatus: %s, nextStatus: %s", nodebInfo.RanName, nodebInfo.GetConnectionStatus(), nextStatus)
+
+       // set the proper event
+       event := m.setEvent(nodebInfo, nextStatus)
+       isConnectivityEvent := event != NONE_RAW_EVENT
+
+       // only after determining event we set next status
+       nodebInfo.ConnectionStatus = nextStatus;
+       if !isConnectivityEvent {
+               err := m.updateNodebInfo(nodebInfo)
+               if err != nil {
+                       return err
+               }
+       } else {
+               err := m.updateNodebInfoOnConnectionStatusInversion(nodebInfo, event)
+               if err != nil {
+                       return err
+               }
+       }
+
+       // in any case, update RanListManager
+       m.logger.Infof("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s, updating RanListManager... status: %s", nodebInfo.RanName, nodebInfo.GetConnectionStatus())
+       err := m.ranListManager.UpdateRanState(nodebInfo)
+       if err != nil {
+               m.logger.Errorf("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s - Failed updating RAN's connection status by RanListManager. Error: %v", nodebInfo.RanName, err)
+               // log and proceed...
+       }
+
+       if isConnectivityEvent {
+               m.logger.Infof("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s, setting alarm at RanAlarmService... event: %s", nodebInfo.RanName, event)
+               err := m.ranAlarmService.SetConnectivityChangeAlarm(nodebInfo)
+               if err != nil {
+                       m.logger.Errorf("#RanConnectStatusChangeManager.ChangeStatus - RAN name: %s - Failed setting an alarm by RanAlarmService. Error: %v", nodebInfo.RanName, err)
+                       // log and proceed...
+               }
+       }
+
+       return nil
+}
+
+func (m *RanConnectStatusChangeManager) updateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, event string) error {
+
+       err := m.rnibDataService.UpdateNodebInfoOnConnectionStatusInversion(nodebInfo, event)
+
+       if err != nil {
+               m.logger.Errorf("#RanConnectStatusChangeManager.updateNodebInfoOnConnectionStatusInversion - RAN name: %s - Failed updating RAN's connection status in rNib. Error: %v", nodebInfo.RanName, err)
+               return err
+       }
+
+       m.logger.Infof("#RanConnectStatusChangeManager.updateNodebInfoOnConnectionStatusInversion - RAN name: %s - Successfully updated rNib.", nodebInfo.RanName)
+       return nil
+}
+
+func (m *RanConnectStatusChangeManager) updateNodebInfo(nodebInfo *entities.NodebInfo) error {
+
+       err := m.rnibDataService.UpdateNodebInfo(nodebInfo)
+
+       if err != nil {
+               m.logger.Errorf("#RanConnectStatusChangeManager.updateNodebInfo - RAN name: %s - Failed updating RAN's connection status in rNib. Error: %v", nodebInfo.RanName, err)
+               return err
+       }
+
+       m.logger.Infof("#RanConnectStatusChangeManager.updateNodebInfo - RAN name: %s - Successfully updated rNib.", nodebInfo.RanName)
+       return nil
+}
+
+func (m *RanConnectStatusChangeManager) setEvent(nodebInfo *entities.NodebInfo, nextState entities.ConnectionStatus) string {
+       currentConnectionStatus := nodebInfo.GetConnectionStatus()
+
+       var event string
+       if currentConnectionStatus != entities.ConnectionStatus_CONNECTED && nextState == entities.ConnectionStatus_CONNECTED {
+               event = nodebInfo.RanName + "_" + CONNECTED_RAW_EVENT
+       } else if currentConnectionStatus == entities.ConnectionStatus_CONNECTED && nextState != entities.ConnectionStatus_CONNECTED {
+               event = nodebInfo.RanName + "_" + DISCONNECTED_RAW_EVENT
+       } else {
+               event = NONE_RAW_EVENT
+       }
+
+       m.logger.Infof("#RanConnectStatusChangeManager.setEvent - Connectivity Event for RAN %s is: %s", nodebInfo.RanName, event)
+       return event
+}
diff --git a/E2Manager/managers/ran_connect_status_change_manager_test.go b/E2Manager/managers/ran_connect_status_change_manager_test.go
new file mode 100644 (file)
index 0000000..b9295e3
--- /dev/null
@@ -0,0 +1,187 @@
+//
+// 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.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package managers
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "e2mgr/mocks"
+       "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"
+       "github.com/pkg/errors"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+const EventChannelForTest = "RAN_CONNECTION_STATUS_CHANGE"
+
+func initRanConnectStatusChangeManagerTest(t *testing.T) (*mocks.RnibWriterMock, *mocks.RanListManagerMock, *mocks.RanAlarmServiceMock, *RanConnectStatusChangeManager) {
+       log, err := logger.InitLogger(logger.DebugLevel)
+       if err != nil {
+               t.Errorf("#... - failed to initialize log, error: %s", err)
+       }
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, StateChangeMessageChannel: EventChannelForTest}
+
+       readerMock := &mocks.RnibReaderMock{}
+       writerMock := &mocks.RnibWriterMock{}
+       rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
+       ranListManagerMock := &mocks.RanListManagerMock{}
+       ranAlarmServiceMock := &mocks.RanAlarmServiceMock{}
+       ranConnectStatusChangeManager := NewRanConnectStatusChangeManager(log, rnibDataService, ranListManagerMock, ranAlarmServiceMock)
+       return writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager
+}
+
+func TestChangeStatusSuccessNewRan(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_UNKNOWN_CONNECTION_STATUS}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED
+       writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNodebInfo, EventChannelForTest, RanName + "_" + CONNECTED_RAW_EVENT).Return(nil)
+       ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil)
+       ranAlarmServiceMock.On("SetConnectivityChangeAlarm", &updatedNodebInfo).Return(nil)
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_CONNECTED)
+       assert.Nil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
+
+func TestChangeStatusSuccessEventNone1(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
+       writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil)
+       ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil)
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_SHUT_DOWN)
+       assert.Nil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
+
+func TestChangeStatusSuccessEventNone2(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
+       writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil)
+       ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil)
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_SHUT_DOWN)
+       assert.Nil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
+
+func TestChangeStatusSuccessEventConnected(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED
+       writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNodebInfo, EventChannelForTest, RanName + "_" + CONNECTED_RAW_EVENT).Return(nil)
+       ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil)
+       ranAlarmServiceMock.On("SetConnectivityChangeAlarm", &updatedNodebInfo).Return(nil)
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_CONNECTED)
+       assert.Nil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
+
+func TestChangeStatusSuccessEventDisconnected(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
+       writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNodebInfo, EventChannelForTest, RanName + "_" + DISCONNECTED_RAW_EVENT).Return(nil)
+       ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil)
+       ranAlarmServiceMock.On("SetConnectivityChangeAlarm", &updatedNodebInfo).Return(nil)
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_DISCONNECTED)
+       assert.Nil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
+
+func TestChangeStatusRnibErrorEventNone(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
+       writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error")))
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_SHUT_DOWN)
+       assert.NotNil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
+
+func TestChangeStatusRnibErrorEventConnected(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED
+       writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNodebInfo, EventChannelForTest, RanName + "_" + CONNECTED_RAW_EVENT).Return(common.NewInternalError(errors.New("Error")))
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_CONNECTED)
+       assert.NotNil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
+
+func TestChangeStatusRanListManagerError(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
+       writerMock.On("UpdateNodebInfo", &updatedNodebInfo).Return(nil)
+       ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error")))
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_SHUT_DOWN)
+       assert.Nil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
+
+func TestChangeStatusRanAlarmServiceErrorEventConnected(t *testing.T) {
+       writerMock, ranListManagerMock, ranAlarmServiceMock, ranConnectStatusChangeManager := initRanConnectStatusChangeManagerTest(t)
+
+       origNodebInfo := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
+       updatedNodebInfo := *origNodebInfo
+       updatedNodebInfo.ConnectionStatus = entities.ConnectionStatus_CONNECTED
+       writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNodebInfo, EventChannelForTest, RanName + "_" + CONNECTED_RAW_EVENT).Return(nil)
+       ranListManagerMock.On("UpdateRanState", &updatedNodebInfo).Return(nil)
+       ranAlarmServiceMock.On("SetConnectivityChangeAlarm", &updatedNodebInfo).Return(common.NewInternalError(errors.New("Error")))
+       err := ranConnectStatusChangeManager.ChangeStatus(origNodebInfo, entities.ConnectionStatus_CONNECTED)
+       assert.Nil(t, err)
+       writerMock.AssertExpectations(t)
+       ranListManagerMock.AssertExpectations(t)
+       ranAlarmServiceMock.AssertExpectations(t)
+}
\ No newline at end of file
diff --git a/E2Manager/managers/ran_list_manager.go b/E2Manager/managers/ran_list_manager.go
new file mode 100644 (file)
index 0000000..9ad10f2
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// 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.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package managers
+
+import (
+       "e2mgr/logger"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+)
+
+type ranListManagerInstance struct {
+       logger *logger.Logger
+}
+
+type RanListManager interface {
+       UpdateRanState(nodebInfo *entities.NodebInfo) error
+}
+
+func NewRanListManager(logger *logger.Logger) RanListManager {
+       return &ranListManagerInstance{
+               logger: logger,
+       }
+}
+
+func (m *ranListManagerInstance) UpdateRanState(nodebInfo *entities.NodebInfo) error {
+       m.logger.Infof("#ranListManagerInstance.UpdateRanState - RAN name: %s - Updating state...", nodebInfo.RanName)
+       return nil
+}
index a164383..11130b3 100644 (file)
@@ -81,3 +81,10 @@ func (c *NodebControllerMock) UpdateGnb(writer http.ResponseWriter, r *http.Requ
 
        c.Called()
 }
+
+func (c *NodebControllerMock) SetGeneralConfiguration(writer http.ResponseWriter, r *http.Request) {
+       writer.Header().Set("Content-Type", "application/json")
+       writer.WriteHeader(http.StatusOK)
+
+       c.Called()
+}
\ No newline at end of file
diff --git a/E2Manager/mocks/ran_alarm_service_mock.go b/E2Manager/mocks/ran_alarm_service_mock.go
new file mode 100644 (file)
index 0000000..ed18c88
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// 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.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package mocks
+
+import (
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/mock"
+)
+
+type RanAlarmServiceMock struct {
+       mock.Mock
+}
+
+func (m *RanAlarmServiceMock) SetConnectivityChangeAlarm(nodebInfo *entities.NodebInfo) error {
+
+       args := m.Called(nodebInfo)
+       return args.Error(0)
+}
\ No newline at end of file
diff --git a/E2Manager/mocks/ran_list_manager_mock.go b/E2Manager/mocks/ran_list_manager_mock.go
new file mode 100644 (file)
index 0000000..6df5c4f
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// 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.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package mocks
+
+import (
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+       "github.com/stretchr/testify/mock"
+)
+
+type RanListManagerMock struct {
+       mock.Mock
+}
+
+func (m *RanListManagerMock) UpdateRanState(nodebInfo *entities.NodebInfo) error {
+
+       args := m.Called(nodebInfo)
+       return args.Error(0)
+}
\ No newline at end of file
index 59c635e..20a7f0a 100644 (file)
@@ -156,3 +156,8 @@ func (m *RnibReaderMock) GetE2TAddresses() ([]string, error) {
        args := m.Called()
        return args.Get(0).([]string), args.Error(1)
 }
+
+func (m *RnibReaderMock) GetGeneralConfiguration() (*entities.GeneralConfiguration, error) {
+       args := m.Called()
+       return args.Get(0).(*entities.GeneralConfiguration), args.Error(1)
+}
\ No newline at end of file
index 5c602bb..3503d10 100644 (file)
@@ -92,3 +92,14 @@ func (rnibWriterMock *RnibWriterMock) RemoveServedNrCells(inventoryName string,
        return args.Error(0)
 }
 
+func (rnibWriterMock *RnibWriterMock) UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error {
+       args := rnibWriterMock.Called(nodebInfo, stateChangeMessageChannel, event)
+
+       return args.Error(0)
+}
+
+func (rnibWriterMock *RnibWriterMock) SaveGeneralConfiguration(config *entities.GeneralConfiguration) error {
+       args := rnibWriterMock.Called(config)
+
+       return args.Error(0)
+}
\ No newline at end of file
diff --git a/E2Manager/models/cause.go b/E2Manager/models/cause.go
new file mode 100644 (file)
index 0000000..15cd7d6
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package models
+
+import "encoding/xml"
+
+type Cause struct {
+       XMLName    xml.Name         `xml:"Cause"`
+       Text       string           `xml:",chardata"`
+       RicRequest *CauseRic        `xml:"ricRequest"`
+       RicService *CauseRicService `xml:"ricService"`
+       Transport  *CauseTransport  `xml:"transport"`
+       Protocol   *CauseProtocol   `xml:"protocol"`
+       Misc       *CauseMisc       `xml:"misc"`
+}
+
+type CauseTransport struct {
+       Text                         string    `xml:",chardata"`
+       TransportResourceUnavailable *struct{} `xml:"transport-resource-unavailable"`
+       Unspecified                  *struct{} `xml:"unspecified"`
+}
+
+type CauseMisc struct {
+       Text                      string    `xml:",chardata"`
+       ControlProcessingOverload *struct{} `xml:"control-processing-overload"`
+       HardwareFailure           *struct{} `xml:"hardware-failure"`
+       OmIntervention            *struct{} `xml:"om-intervention"`
+       Unspecified               *struct{} `xml:"unspecified"`
+}
+
+type CauseProtocol struct {
+       Text                                         string    `xml:",chardata"`
+       TransferSyntaxError                          *struct{} `xml:"transfer-syntax-error"`
+       AbstractSyntaxErrorReject                    *struct{} `xml:"abstract-syntax-error-reject"`
+       AbstractSyntaxErrorIgnoreAndNotify           *struct{} `xml:"abstract-syntax-error-ignore-and-notify"`
+       MessageNotCompatibleWithReceiverState        *struct{} `xml:"message-not-compatible-with-receiver-state"`
+       SemanticError                                *struct{} `xml:"semantic-error"`
+       AbstractSyntaxErrorFalselyConstructedMessage *struct{} `xml:"abstract-syntax-error-falsely-constructed-message"`
+       Unspecified                                  *struct{} `xml:"unspecified"`
+}
+
+type CauseRicService struct {
+       Text                string    `xml:",chardata"`
+       FunctionNotRequired *struct{} `xml:"function-not-required"`
+       ExcessiveFunctions  *struct{} `xml:"excessive-functions"`
+       RicResourceLimit    *struct{} `xml:"ric-resource-limit"`
+}
+
+type CauseRic struct {
+       Text                                       string    `xml:",chardata"`
+       RanFunctionIdInvalid                       *struct{} `xml:"ran-function-id-Invalid"`
+       ActionNotSupported                         *struct{} `xml:"action-not-supported"`
+       ExcessiveActions                           *struct{} `xml:"excessive-actions"`
+       DuplicateAction                            *struct{} `xml:"duplicate-action"`
+       DuplicateEvent                             *struct{} `xml:"duplicate-event"`
+       FunctionResourceLimit                      *struct{} `xml:"function-resource-limit"`
+       RequestIdUnknown                           *struct{} `xml:"request-id-unknown"`
+       InconsistentActionSubsequentActionSequence *struct{} `xml:"inconsistent-action-subsequent-action-sequence"`
+       ControlMessageInvalid                      *struct{} `xml:"control-message-invalid"`
+       CallProcessIdInvalid                       *struct{} `xml:"call-process-id-invalid"`
+       Unspecified                                *struct{} `xml:"unspecified"`
+}
index 32d05ca..e61d498 100644 (file)
@@ -21,10 +21,8 @@ package models
 
 import (
        "encoding/xml"
-       "errors"
-       "fmt"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
-       "strconv"
+       "github.com/golang/protobuf/ptypes/wrappers"
        "strings"
 )
 
@@ -134,10 +132,119 @@ type E2SetupRequestMessage struct {
 }
 
 type RanFunctionItem struct {
-       Text                  string `xml:",chardata"`
-       RanFunctionID         string `xml:"ranFunctionID"`
-       RanFunctionDefinition string `xml:"ranFunctionDefinition"`
-       RanFunctionRevision   string `xml:"ranFunctionRevision"`
+       Text                  string                `xml:",chardata"`
+       RanFunctionID         uint32                `xml:"ranFunctionID"`
+       RanFunctionDefinition RanFunctionDefinition `xml:"ranFunctionDefinition"`
+       RanFunctionRevision   uint32                `xml:"ranFunctionRevision"`
+}
+
+type RanFunctionDefinition struct {
+       Text                            string                          `xml:",chardata"`
+       E2smGnbNrtRanFunctionDefinition E2smGnbNrtRanFunctionDefinition `xml:"E2SM-gNB-NRT-RANfunction-Definition"`
+}
+
+type RanFunctionName struct {
+       Text                   string  `xml:",chardata"`
+       RanFunctionShortName   string  `xml:"ranFunction-ShortName"`
+       RanFunctionE2smOid     string  `xml:"ranFunction-E2SM-OID"`
+       RanFunctionDescription string  `xml:"ranFunction-Description"`
+       RanFunctionInstance    *uint32 `xml:"ranFunction-Instance"`
+}
+
+type RicEventTriggerStyleList struct {
+       Text                      string `xml:",chardata"`
+       RicEventTriggerStyleType  uint32 `xml:"ric-EventTriggerStyle-Type"`
+       RicEventTriggerStyleName  string `xml:"ric-EventTriggerStyle-Name"`
+       RicEventTriggerFormatType uint32 `xml:"ric-EventTriggerFormat-Type"`
+}
+
+type RanParameterDefItem struct {
+       Text             string           `xml:",chardata"`
+       RanParameterID   uint32           `xml:"ranParameter-ID"`
+       RanParameterName string           `xml:"ranParameter-Name"`
+       RanParameterType RanParameterType `xml:"ranParameter-Type"`
+}
+
+type RanParameterType struct {
+       Text            string    `xml:",chardata"`
+       Boolean         *struct{} `xml:"boolean,omitempty"`
+       Integer         *struct{} `xml:"integer,omitempty"`
+       Enumerated      *struct{} `xml:"enumerated,omitempty"`
+       BitString       *struct{} `xml:"bit-string,omitempty"`
+       OctetString     *struct{} `xml:"octet-string,omitempty"`
+       PrintableString *struct{} `xml:"printable-string,omitempty"`
+}
+
+type RicReportStyleList struct {
+       Text                         string `xml:",chardata"`
+       RicReportStyleType           uint32 `xml:"ric-ReportStyle-Type"`
+       RicReportStyleName           string `xml:"ric-ReportStyle-Name"`
+       RicReportActionFormatType    uint32 `xml:"ric-ReportActionFormat-Type"`
+       RicReportRanParameterDefList struct {
+               Text                string                `xml:",chardata"`
+               RanParameterDefItem []RanParameterDefItem `xml:"RANparameterDef-Item"`
+       } `xml:"ric-ReportRanParameterDef-List"`
+       RicIndicationHeaderFormatType  uint32 `xml:"ric-IndicationHeaderFormat-Type"`
+       RicIndicationMessageFormatType uint32 `xml:"ric-IndicationMessageFormat-Type"`
+}
+
+type RicInsertStyleList struct {
+       Text                         string `xml:",chardata"`
+       RicInsertStyleType           uint32 `xml:"ric-InsertStyle-Type"`
+       RicInsertStyleName           string `xml:"ric-InsertStyle-Name"`
+       RicInsertActionFormatType    uint32 `xml:"ric-InsertActionFormat-Type"`
+       RicInsertRanParameterDefList struct {
+               Text                string                `xml:",chardata"`
+               RanParameterDefItem []RanParameterDefItem `xml:"RANparameterDef-Item"`
+       } `xml:"ric-InsertRanParameterDef-List"`
+       RicIndicationHeaderFormatType  uint32 `xml:"ric-IndicationHeaderFormat-Type"`
+       RicIndicationMessageFormatType uint32 `xml:"ric-IndicationMessageFormat-Type"`
+       RicCallProcessIdFormatType     uint32 `xml:"ric-CallProcessIDFormat-Type"`
+}
+
+type RicControlStyleList struct {
+       Text                        string `xml:",chardata"`
+       RicControlStyleType         uint32 `xml:"ric-ControlStyle-Type"`
+       RicControlStyleName         string `xml:"ric-ControlStyle-Name"`
+       RicControlHeaderFormatType  uint32 `xml:"ric-ControlHeaderFormat-Type"`
+       RicControlMessageFormatType uint32 `xml:"ric-ControlMessageFormat-Type"`
+       RicCallProcessIdFormatType  uint32 `xml:"ric-CallProcessIDFormat-Type"`
+}
+
+type RicPolicyStyleList struct {
+       Text                         string `xml:",chardata"`
+       RicPolicyStyleType           uint32 `xml:"ric-PolicyStyle-Type"`
+       RicPolicyStyleName           string `xml:"ric-PolicyStyle-Name"`
+       RicPolicyActionFormatType    uint32 `xml:"ric-PolicyActionFormat-Type"`
+       RicPolicyRanParameterDefList struct {
+               Text                string                `xml:",chardata"`
+               RanParameterDefItem []RanParameterDefItem `xml:"RANparameterDef-Item"`
+       } `xml:"ric-PolicyRanParameterDef-List"`
+}
+
+type E2smGnbNrtRanFunctionDefinition struct {
+       Text                     string          `xml:",chardata"`
+       RanFunctionName          RanFunctionName `xml:"ranFunction-Name"`
+       RicEventTriggerStyleList struct {
+               Text                     string                     `xml:",chardata"`
+               RicEventTriggerStyleList []RicEventTriggerStyleList `xml:"RIC-EventTriggerStyle-List"`
+       } `xml:"ric-EventTriggerStyle-List"`
+       RicReportStyleList struct {
+               Text               string               `xml:",chardata"`
+               RicReportStyleList []RicReportStyleList `xml:"RIC-ReportStyle-List"`
+       } `xml:"ric-ReportStyle-List"`
+       RicInsertStyleList struct {
+               Text               string               `xml:",chardata"`
+               RicInsertStyleList []RicInsertStyleList `xml:"RIC-InsertStyle-List"`
+       } `xml:"ric-InsertStyle-List"`
+       RicControlStyleList struct {
+               Text                string                `xml:",chardata"`
+               RicControlStyleList []RicControlStyleList `xml:"RIC-ControlStyle-List"`
+       } `xml:"ric-ControlStyle-List"`
+       RicPolicyStyleList struct {
+               Text               string               `xml:",chardata"`
+               RicPolicyStyleList []RicPolicyStyleList `xml:"RIC-PolicyStyle-List"`
+       } `xml:"ric-PolicyStyle-List"`
 }
 
 type RANfunctionsList struct {
@@ -156,54 +263,219 @@ type RANfunctionsList struct {
        } `xml:"ProtocolIE-SingleContainer"`
 }
 
-func (m *E2SetupRequestMessage) ExtractRanFunctionsList() ([]*entities.RanFunction, error) {
+func (m *E2SetupRequestMessage) ExtractRanFunctionsList() []*entities.RanFunction {
+       // TODO: verify e2SetupRequestIEs structure with Adi
+       e2SetupRequestIes := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs
+       if len(e2SetupRequestIes) < 2  {
+               return nil
+       }
+
+       ranFunctionsListContainer := e2SetupRequestIes[1].Value.RANfunctionsList.ProtocolIESingleContainer
+       funcs := make([]*entities.RanFunction, len(ranFunctionsListContainer))
+       for i := 0; i < len(funcs); i++ {
+               ranFunctionItem := ranFunctionsListContainer[i].Value.RANfunctionItem
+
+               funcs[i] = &entities.RanFunction{
+                       RanFunctionId:         &wrappers.UInt32Value{Value: ranFunctionItem.RanFunctionID},
+                       RanFunctionDefinition: m.buildRanFunctionDefinitionProto(&ranFunctionItem.RanFunctionDefinition),
+                       RanFunctionRevision:   &wrappers.UInt32Value{Value: ranFunctionItem.RanFunctionRevision},
+               }
+       }
+       return funcs
+}
+
+func (m *E2SetupRequestMessage) buildRanFunctionDefinitionProto(def *RanFunctionDefinition) *entities.RanFunctionDefinition {
+       return &entities.RanFunctionDefinition{
+               E2SmGnbNrtRanFunctionDefinition: &entities.E2SmGnbNrtRanFunctionDefinition{
+                       RanFunctionName:       buildRanFunctionNameProto(def),
+                       RicEventTriggerStyles: buildRicEventTriggerStylesProto(def),
+                       RicReportStyles:       buildRicReportStylesProto(def),
+                       RicInsertStyles:       buildRicInsertStylesProto(def),
+                       RicControlStyles:      buildRicControlStylesProto(def),
+                       RicPolicyStyles:       buildRicPolicyStylesProto(def),
+               },
+       }
+}
 
-       setupRequestIes := m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs
+func buildRanFunctionNameProto(def *RanFunctionDefinition) *entities.RanFunctionName {
+       defRanFunctionName := def.E2smGnbNrtRanFunctionDefinition.RanFunctionName
+       ranFunctionName := &entities.RanFunctionName{
+               RanFunctionShortName:   &wrappers.StringValue{Value: defRanFunctionName.RanFunctionShortName},
+               RanFunctionE2SmOid:     &wrappers.StringValue{Value: defRanFunctionName.RanFunctionE2smOid},
+               RanFunctionDescription: &wrappers.StringValue{Value: defRanFunctionName.RanFunctionDescription},
+       }
 
-       if len(setupRequestIes) < 2 {
-               return nil, nil
+       if defRanFunctionName.RanFunctionInstance != nil {
+               ranFunctionName.OptionalRanFunctionInstance = &entities.RanFunctionName_RanFunctionInstance{
+                       RanFunctionInstance: *defRanFunctionName.RanFunctionInstance,
+               }
        }
 
-       list := setupRequestIes[1].Value.RANfunctionsList.ProtocolIESingleContainer
-       funcs := make([]*entities.RanFunction, len(list))
-       for i := 0; i < len(funcs); i++ {
-               funcs[i] = &entities.RanFunction{}
-               id, err := strconv.ParseUint(list[i].Value.RANfunctionItem.RanFunctionID, 10, 32)
-               if err != nil {
-                       return nil, errors.New(fmt.Sprintf("#e2_setup_request_message.ExtractRanFunctionsList - Failed parse uint RanFunctionID from %s", list[i].Value.RANfunctionItem.RanFunctionID))
+       return ranFunctionName
+}
+
+func buildRicEventTriggerStylesProto(def *RanFunctionDefinition) []*entities.RicEventTriggerStyle {
+       defRicEventTriggerStyleList := def.E2smGnbNrtRanFunctionDefinition.RicEventTriggerStyleList.RicEventTriggerStyleList
+       ricEventTriggerStyles := make([]*entities.RicEventTriggerStyle, len(defRicEventTriggerStyleList))
+
+       for i, v := range defRicEventTriggerStyleList {
+               ricEventTriggerStyles[i] = &entities.RicEventTriggerStyle{
+                       RicEventTriggerStyleType:  &wrappers.UInt32Value{Value: v.RicEventTriggerStyleType},
+                       RicEventTriggerStyleName:  &wrappers.StringValue{Value: v.RicEventTriggerStyleName},
+                       RicEventTriggerFormatType: &wrappers.UInt32Value{Value: v.RicEventTriggerFormatType},
                }
-               funcs[i].RanFunctionId = uint32(id)
-               rev, err := strconv.ParseUint(list[i].Value.RANfunctionItem.RanFunctionRevision, 10, 32)
-               if err != nil {
-                       return nil, errors.New(fmt.Sprintf("#e2_setup_request_message.ExtractRanFunctionsList - Failed parse uint RanFunctionRevision from %s", list[i].Value.RANfunctionItem.RanFunctionRevision))
+       }
+
+       return ricEventTriggerStyles
+}
+
+func buildRicReportStylesProto(def *RanFunctionDefinition) []*entities.RicReportStyle {
+       defRicReportStyleList := def.E2smGnbNrtRanFunctionDefinition.RicReportStyleList.RicReportStyleList
+       ricReportStyles := make([]*entities.RicReportStyle, len(defRicReportStyleList))
+
+       for i, v := range defRicReportStyleList {
+               ricReportStyles[i] = &entities.RicReportStyle{
+                       RicReportStyleType:             &wrappers.UInt32Value{Value: v.RicReportStyleType},
+                       RicReportStyleName:             &wrappers.StringValue{Value: v.RicReportStyleName},
+                       RicReportActionFormatType:      &wrappers.UInt32Value{Value: v.RicReportActionFormatType},
+                       RicReportRanParameterDefs:      buildRicReportRanParameterDefsProto(v),
+                       RicIndicationHeaderFormatType:  &wrappers.UInt32Value{Value: v.RicIndicationHeaderFormatType},
+                       RicIndicationMessageFormatType: &wrappers.UInt32Value{Value: v.RicIndicationMessageFormatType},
                }
-               funcs[i].RanFunctionDefinition = m.trimSpaces(list[i].Value.RANfunctionItem.RanFunctionDefinition)
-               funcs[i].RanFunctionRevision = uint32(rev)
        }
-       return funcs, nil
+
+       return ricReportStyles
+}
+
+func buildRicReportRanParameterDefsProto(ricReportStyleList RicReportStyleList) []*entities.RanParameterDef {
+       ricReportRanParameterDefList := ricReportStyleList.RicReportRanParameterDefList.RanParameterDefItem
+       ranParameterDefs := make([]*entities.RanParameterDef, len(ricReportRanParameterDefList))
+
+       for i, v := range ricReportRanParameterDefList {
+               ranParameterDefs[i] = &entities.RanParameterDef{
+                       RanParameterId:   &wrappers.UInt32Value{Value: v.RanParameterID},
+                       RanParameterName: &wrappers.StringValue{Value: v.RanParameterName},
+                       RanParameterType: getRanParameterTypeEnumValue(v.RanParameterType),
+               }
+       }
+
+       return ranParameterDefs
+}
+
+func getRanParameterTypeEnumValue(ranParameterType RanParameterType) entities.RanParameterType {
+       if ranParameterType.Boolean != nil {
+               return entities.RanParameterType_BOOLEAN
+       }
+
+       if ranParameterType.BitString != nil {
+               return entities.RanParameterType_BIT_STRING
+       }
+
+       if ranParameterType.Enumerated != nil {
+               return entities.RanParameterType_ENUMERATED
+       }
+
+       if ranParameterType.Integer != nil {
+               return entities.RanParameterType_INTEGER
+       }
+
+       if ranParameterType.OctetString != nil {
+               return entities.RanParameterType_OCTET_STRING
+       }
+
+       if ranParameterType.PrintableString != nil {
+               return entities.RanParameterType_PRINTABLE_STRING
+       }
+
+       return entities.RanParameterType_UNKNOWN_RAN_PARAMETER_TYPE
+}
+
+func buildRicInsertStylesProto(def *RanFunctionDefinition) []*entities.RicInsertStyle {
+       defRicInsertStyleList := def.E2smGnbNrtRanFunctionDefinition.RicInsertStyleList.RicInsertStyleList
+       ricInsertStyles := make([]*entities.RicInsertStyle, len(defRicInsertStyleList))
+
+       for i, v := range defRicInsertStyleList {
+               ricInsertStyles[i] = &entities.RicInsertStyle{
+                       RicInsertStyleType:             &wrappers.UInt32Value{Value: v.RicInsertStyleType},
+                       RicInsertStyleName:             &wrappers.StringValue{Value: v.RicInsertStyleName},
+                       RicInsertActionFormatType:      &wrappers.UInt32Value{Value: v.RicInsertActionFormatType},
+                       RicInsertRanParameterDefs:      buildRicInsertRanParameterDefsProto(v),
+                       RicIndicationHeaderFormatType:  &wrappers.UInt32Value{Value: v.RicIndicationHeaderFormatType},
+                       RicIndicationMessageFormatType: &wrappers.UInt32Value{Value: v.RicIndicationMessageFormatType},
+                       RicCallProcessIdFormatType:     &wrappers.UInt32Value{Value: v.RicCallProcessIdFormatType},
+               }
+       }
+
+       return ricInsertStyles
+}
+
+func buildRicInsertRanParameterDefsProto(ricInsertStyleList RicInsertStyleList) []*entities.RanParameterDef {
+       ricInsertRanParameterDefList := ricInsertStyleList.RicInsertRanParameterDefList.RanParameterDefItem
+       ranParameterDefs := make([]*entities.RanParameterDef, len(ricInsertRanParameterDefList))
+
+       for i, v := range ricInsertRanParameterDefList {
+               ranParameterDefs[i] = &entities.RanParameterDef{
+                       RanParameterId:   &wrappers.UInt32Value{Value: v.RanParameterID},
+                       RanParameterName: &wrappers.StringValue{Value: v.RanParameterName},
+                       RanParameterType: getRanParameterTypeEnumValue(v.RanParameterType),
+               }
+       }
+
+       return ranParameterDefs
+}
+
+func buildRicControlStylesProto(def *RanFunctionDefinition) []*entities.RicControlStyle {
+       defRicControlStyleList := def.E2smGnbNrtRanFunctionDefinition.RicControlStyleList.RicControlStyleList
+       ricControlStyles := make([]*entities.RicControlStyle, len(defRicControlStyleList))
+
+       for i, v := range defRicControlStyleList {
+               ricControlStyles[i] = &entities.RicControlStyle{
+                       RicControlStyleType:         &wrappers.UInt32Value{Value: v.RicControlStyleType},
+                       RicControlStyleName:         &wrappers.StringValue{Value: v.RicControlStyleName},
+                       RicControlHeaderFormatType:  &wrappers.UInt32Value{Value: v.RicControlHeaderFormatType},
+                       RicControlMessageFormatType: &wrappers.UInt32Value{Value: v.RicControlMessageFormatType},
+                       RicCallProcessIdFormatType:  &wrappers.UInt32Value{Value: v.RicCallProcessIdFormatType},
+               }
+       }
+
+       return ricControlStyles
+}
+
+func buildRicPolicyRanParameterDefsProto(ricPolicyStyleList RicPolicyStyleList) []*entities.RanParameterDef {
+       ricPolicyRanParameterDefList := ricPolicyStyleList.RicPolicyRanParameterDefList.RanParameterDefItem
+       ranParameterDefs := make([]*entities.RanParameterDef, len(ricPolicyRanParameterDefList))
+
+       for i, v := range ricPolicyRanParameterDefList {
+               ranParameterDefs[i] = &entities.RanParameterDef{
+                       RanParameterId:   &wrappers.UInt32Value{Value: v.RanParameterID},
+                       RanParameterName: &wrappers.StringValue{Value: v.RanParameterName},
+                       RanParameterType: getRanParameterTypeEnumValue(v.RanParameterType),
+               }
+       }
+
+       return ranParameterDefs
+}
+
+func buildRicPolicyStylesProto(def *RanFunctionDefinition) []*entities.RicPolicyStyle {
+       defRicPolicyStyleList := def.E2smGnbNrtRanFunctionDefinition.RicPolicyStyleList.RicPolicyStyleList
+       ricPolicyStyles := make([]*entities.RicPolicyStyle, len(defRicPolicyStyleList))
+
+       for i, v := range defRicPolicyStyleList {
+               ricPolicyStyles[i] = &entities.RicPolicyStyle{
+                       RicPolicyStyleType:        &wrappers.UInt32Value{Value: v.RicPolicyStyleType},
+                       RicPolicyStyleName:        &wrappers.StringValue{Value: v.RicPolicyStyleName},
+                       RicPolicyActionFormatType: &wrappers.UInt32Value{Value: v.RicPolicyActionFormatType},
+                       RicPolicyRanParameterDefs: buildRicPolicyRanParameterDefsProto(v),
+               }
+       }
+
+       return ricPolicyStyles
 }
 
 func (m *E2SetupRequestMessage) getGlobalE2NodeId() GlobalE2NodeId {
        return m.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[0].Value.GlobalE2nodeID
 }
 
-//func (m *E2SetupRequestMessage) GetNodeType() entities.Node_Type {
-//     globalE2NodeId := m.getGlobalE2NodeId()
-//     if id := globalE2NodeId.GNB.GlobalGNBID.PlmnID; id != "" {
-//             return entities.Node_GNB
-//     }
-//     if id := globalE2NodeId.EnGNB.GlobalGNBID.PlmnID; id != "" {
-//             return entities.Node_GNB
-//     }
-//     if id := globalE2NodeId.ENB.GlobalENBID.PlmnID; id != "" {
-//             return entities.Node_ENB
-//     }
-//     if id := globalE2NodeId.NgENB.GlobalNgENBID.PlmnID; id != "" {
-//             return entities.Node_ENB
-//     }
-//     return entities.Node_UNKNOWN
-//}
-
 func (m *E2SetupRequestMessage) GetPlmnId() string {
        globalE2NodeId := m.getGlobalE2NodeId()
        if id := globalE2NodeId.GNB.GlobalGNBID.PlmnID; id != "" {
index 798f784..04d63a1 100644 (file)
@@ -71,9 +71,9 @@ func NewE2SetupSuccessResponseMessage(plmnId string, ricId string, request *E2Se
        outcome := SuccessfulOutcome{}
        outcome.ProcedureCode = "1"
 
-       setupRequestIes := request.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs
+       e2SetupRequestIes := request.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs
 
-       outcome.Value.E2setupResponse.ProtocolIEs.E2setupResponseIEs = make([]E2setupResponseIEs, len(setupRequestIes))
+       outcome.Value.E2setupResponse.ProtocolIEs.E2setupResponseIEs = make([]E2setupResponseIEs, len(e2SetupRequestIes))
        outcome.Value.E2setupResponse.ProtocolIEs.E2setupResponseIEs[0].ID = "4"
        outcome.Value.E2setupResponse.ProtocolIEs.E2setupResponseIEs[0].Value = GlobalRICID{GlobalRICID: struct {
                Text         string `xml:",chardata"`
@@ -81,27 +81,25 @@ func NewE2SetupSuccessResponseMessage(plmnId string, ricId string, request *E2Se
                RicID        string `xml:"ric-ID"`
        }{PLMNIdentity: plmnId, RicID: ricId}}
 
-       if len(setupRequestIes) < 2 {
+       if len(e2SetupRequestIes) < 2 {
                return E2SetupResponseMessage{E2APPDU: E2APPDU{Outcome: outcome}}
        }
 
-       functionsIdList := extractRanFunctionsIDList(request)
-
        outcome.Value.E2setupResponse.ProtocolIEs.E2setupResponseIEs[1].ID = "9"
        outcome.Value.E2setupResponse.ProtocolIEs.E2setupResponseIEs[1].Value = RANfunctionsIDList{RANfunctionsIDList: struct {
                Text                      string                      `xml:",chardata"`
                ProtocolIESingleContainer []ProtocolIESingleContainer `xml:"ProtocolIE-SingleContainer"`
-       }{ProtocolIESingleContainer: functionsIdList}}
-
+       }{ProtocolIESingleContainer: extractRanFunctionsIDList(request)}}
        return E2SetupResponseMessage{E2APPDU: E2APPDU{Outcome: outcome}}
 }
 
-func NewE2SetupFailureResponseMessage(timeToWait TimeToWait) E2SetupResponseMessage {
+func NewE2SetupFailureResponseMessage(timeToWait TimeToWait, cause Cause) E2SetupResponseMessage {
        outcome := UnsuccessfulOutcome{}
        outcome.Value.E2setupFailure.ProtocolIEs.E2setupFailureIEs = make([]E2setupFailureIEs, 2)
        outcome.ProcedureCode = "1"
        outcome.Value.E2setupFailure.ProtocolIEs.E2setupFailureIEs[0].ID = "1"
-       outcome.Value.E2setupFailure.ProtocolIEs.E2setupFailureIEs[0].Value.Value = Cause{}
+
+       outcome.Value.E2setupFailure.ProtocolIEs.E2setupFailureIEs[0].Value.Value = cause
        outcome.Value.E2setupFailure.ProtocolIEs.E2setupFailureIEs[1].ID = "31"
        outcome.Value.E2setupFailure.ProtocolIEs.E2setupFailureIEs[1].Value.Value = timeToWaitMap[timeToWait]
        return E2SetupResponseMessage{E2APPDU: E2APPDU{Outcome: outcome}}
@@ -177,8 +175,8 @@ type ProtocolIESingleContainer struct {
                Text              string `xml:",chardata"`
                RANfunctionIDItem struct {
                        Text                string `xml:",chardata"`
-                       RanFunctionID       string `xml:"ranFunctionID"`
-                       RanFunctionRevision string `xml:"ranFunctionRevision"`
+                       RanFunctionID       uint32 `xml:"ranFunctionID"`
+                       RanFunctionRevision uint32 `xml:"ranFunctionRevision"`
                } `xml:"RANfunctionID-Item"`
        } `xml:"value"`
 }
@@ -216,17 +214,7 @@ type E2setupFailureIEs struct {
        } `xml:"value"`
 }
 
-type Cause struct {
-       XMLName   xml.Name `xml:"Cause"`
-       Text      string   `xml:",chardata"`
-       Transport struct {
-               Text                         string `xml:",chardata"`
-               TransportResourceUnavailable string `xml:"transport-resource-unavailable"`
-       } `xml:"transport"`
-}
-
 func extractRanFunctionsIDList(request *E2SetupRequestMessage) []ProtocolIESingleContainer {
-
        list := &request.E2APPDU.InitiatingMessage.Value.E2setupRequest.ProtocolIEs.E2setupRequestIEs[1].Value.RANfunctionsList
        ids := make([]ProtocolIESingleContainer, len(list.ProtocolIESingleContainer))
        for i := 0; i < len(ids); i++ {
diff --git a/E2Manager/models/general_configuration_request.go b/E2Manager/models/general_configuration_request.go
new file mode 100644 (file)
index 0000000..5a642ad
--- /dev/null
@@ -0,0 +1,23 @@
+//
+// 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 GeneralConfigurationRequest struct {
+       EnableRic       bool    `json:"enableRic"`
+}
diff --git a/E2Manager/models/general_configuration_response.go b/E2Manager/models/general_configuration_response.go
new file mode 100644 (file)
index 0000000..f19761c
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// 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.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+
+package models
+
+import (
+       "e2mgr/e2managererrors"
+       "encoding/json"
+)
+
+type GeneralConfigurationResponse struct {
+       EnableRic       bool    `json:"enableRic"`
+}
+
+func (response *GeneralConfigurationResponse) Marshal() ([]byte, error) {
+
+       data, err := json.Marshal(response)
+
+       if err != nil {
+               return nil, e2managererrors.NewInternalError()
+       }
+
+       return data, nil
+}
\ No newline at end of file
index f5572cd..9e45372 100644 (file)
@@ -34,14 +34,15 @@ import (
 type IncomingRequest string
 
 const (
-       ShutdownRequest        IncomingRequest = "Shutdown"
-       ResetRequest           IncomingRequest = "Reset"
-       X2SetupRequest         IncomingRequest = "X2SetupRequest"
-       EndcSetupRequest       IncomingRequest = "EndcSetupRequest"
-       GetNodebRequest        IncomingRequest = "GetNodebRequest"
-       GetNodebIdListRequest  IncomingRequest = "GetNodebIdListRequest"
-       GetE2TInstancesRequest IncomingRequest = "GetE2TInstancesRequest"
-       UpdateGnbRequest       IncomingRequest = "UpdateGnbRequest"
+       SetGeneralConfigurationRequest IncomingRequest = "SetGeneralConfiguration"
+       ShutdownRequest                IncomingRequest = "Shutdown"
+       ResetRequest                   IncomingRequest = "Reset"
+       X2SetupRequest                 IncomingRequest = "X2SetupRequest"
+       EndcSetupRequest               IncomingRequest = "EndcSetupRequest"
+       GetNodebRequest                IncomingRequest = "GetNodebRequest"
+       GetNodebIdListRequest          IncomingRequest = "GetNodebIdListRequest"
+       GetE2TInstancesRequest         IncomingRequest = "GetE2TInstancesRequest"
+       UpdateGnbRequest               IncomingRequest = "UpdateGnbRequest"
 )
 
 type IncomingRequestHandlerProvider struct {
@@ -60,14 +61,15 @@ func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrSender *rmrsend
 func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, e2tAssociationManager *managers.E2TAssociationManager, rmClient clients.IRoutingManagerClient) map[IncomingRequest]httpmsghandlers.RequestHandler {
 
        return map[IncomingRequest]httpmsghandlers.RequestHandler{
-               ShutdownRequest:        httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient),
-               ResetRequest:           httpmsghandlers.NewX2ResetRequestHandler(logger, rmrSender, rNibDataService),
-               X2SetupRequest:         httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager),
-               EndcSetupRequest:       httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager),
-               GetNodebRequest:        httpmsghandlers.NewGetNodebRequestHandler(logger, rNibDataService),
-               GetNodebIdListRequest:  httpmsghandlers.NewGetNodebIdListRequestHandler(logger, rNibDataService),
-               GetE2TInstancesRequest: httpmsghandlers.NewGetE2TInstancesRequestHandler(logger, e2tInstancesManager),
-               UpdateGnbRequest:       httpmsghandlers.NewUpdateGnbRequestHandler(logger, rNibDataService),
+               ShutdownRequest:                httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient),
+               ResetRequest:                   httpmsghandlers.NewX2ResetRequestHandler(logger, rmrSender, rNibDataService),
+               X2SetupRequest:                 httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager),
+               EndcSetupRequest:               httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager),
+               GetNodebRequest:                httpmsghandlers.NewGetNodebRequestHandler(logger, rNibDataService),
+               GetNodebIdListRequest:          httpmsghandlers.NewGetNodebIdListRequestHandler(logger, rNibDataService),
+               GetE2TInstancesRequest:         httpmsghandlers.NewGetE2TInstancesRequestHandler(logger, e2tInstancesManager),
+               UpdateGnbRequest:               httpmsghandlers.NewUpdateGnbRequestHandler(logger, rNibDataService),
+               SetGeneralConfigurationRequest: httpmsghandlers.NewSetGeneralConfigurationHandler(logger, rNibDataService),
        }
 }
 
index e06105f..3a04f0b 100644 (file)
@@ -78,6 +78,18 @@ func TestShutdownRequestHandler(t *testing.T) {
        assert.True(t, ok)
 }
 
+func TestSetGeneralConfigurationHandler(t *testing.T) {
+       provider := setupTest(t)
+       handler, err := provider.GetHandler(SetGeneralConfigurationRequest)
+
+       assert.NotNil(t, provider)
+       assert.Nil(t, err)
+
+       _, ok := handler.(*httpmsghandlers.SetGeneralConfigurationHandler)
+
+       assert.True(t, ok)
+}
+
 func TestX2SetupRequestHandler(t *testing.T) {
        provider := setupTest(t)
        handler, err := provider.GetHandler(X2SetupRequest)
index a44f388..3186d70 100644 (file)
@@ -45,6 +45,8 @@ type RNibWriter interface {
        RemoveE2TInstance(e2tAddress string) error
        UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error
        RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error
+       UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error
+       SaveGeneralConfiguration(config *entities.GeneralConfiguration) error
 }
 
 /*
@@ -67,6 +69,17 @@ func (w *rNibWriterInstance) RemoveServedNrCells(inventoryName string, servedNrC
        return nil
 }
 
+func (w *rNibWriterInstance) SaveGeneralConfiguration(config *entities.GeneralConfiguration) error {
+
+       err := w.SaveWithKeyAndMarshal(common.BuildGeneralConfigurationKey(), config)
+
+       if err != nil {
+               return common.NewInternalError(err)
+       }
+
+       return nil
+}
+
 /*
 SaveNodeb saves nodeB entity data in the redis DB according to the specified data model
 */
@@ -315,6 +328,46 @@ func (w *rNibWriterInstance) RemoveE2TInstance(address string) error {
        return nil
 }
 
+func (w *rNibWriterInstance) SaveWithKeyAndMarshal(key string, entity interface{}) error {
+
+       data, err := json.Marshal(entity)
+
+       if err != nil {
+               return common.NewInternalError(err)
+       }
+
+       var pairs []interface{}
+       pairs = append(pairs, key, data)
+
+       err = w.sdl.Set(pairs)
+
+       if err != nil {
+               return common.NewInternalError(err)
+       }
+
+       return nil
+}
+
+/*
+UpdateNodebInfoOnConnectionStatusInversion...
+*/
+func (w *rNibWriterInstance) UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, stateChangeMessageChannel string, event string) error {
+
+       pairs, err := buildUpdateNodebInfoPairs(nodebInfo)
+
+       if err != nil {
+               return err
+       }
+
+       err = w.sdl.SetAndPublish([]string{stateChangeMessageChannel, event}, pairs)
+
+       if err != nil {
+               return common.NewInternalError(err)
+       }
+
+       return nil
+}
+
 /*
 Close the writer
 */
@@ -366,4 +419,4 @@ func appendGnbCells(inventoryName string, cells []*entities.ServedNRCell, pairs
 
 func isNotEmpty(nbIdentity *entities.NbIdentity) bool {
        return nbIdentity.GlobalNbId != nil && nbIdentity.GlobalNbId.PlmnId != "" && nbIdentity.GlobalNbId.NbId != ""
-}
+}
\ No newline at end of file
index 257bb85..ec21c3f 100644 (file)
@@ -564,13 +564,12 @@ func TestSaveNilEntityFailure(t *testing.T) {
 
 func TestSaveUnknownTypeEntityFailure(t *testing.T) {
        w, _ := initSdlInstanceMock(namespace)
-       expectedErr := common.NewValidationError("#rNibWriter.saveNodeB - Unknown responding node type, entity: ip:\"localhost\" port:5656 ")
        nbIdentity := &entities.NbIdentity{InventoryName: "name", GlobalNbId: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"}}
        nb := &entities.NodebInfo{}
        nb.Port = 5656
        nb.Ip = "localhost"
        actualErr := w.SaveNodeb(nbIdentity, nb)
-       assert.Equal(t, expectedErr, actualErr)
+       assert.IsType(t, &common.ValidationError{}, actualErr)
 }
 
 func TestSaveEntityFailure(t *testing.T) {
@@ -743,6 +742,114 @@ func TestRemoveE2TInstanceEmptyAddressFailure(t *testing.T) {
        sdlInstanceMock.AssertExpectations(t)
 }
 
+func TestUpdateNodebInfoOnConnectionStatusInversionSuccess(t *testing.T) {
+       inventoryName := "name"
+       plmnId := "02f829"
+       nbId := "4a952a0a"
+       channelName := "RAN_CONNECT_STATE_CHANGE"
+       eventName := inventoryName + "_" + "CONNECTED"
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+       nodebInfo := generateNodebInfo(inventoryName, entities.Node_ENB, plmnId, nbId)
+       data, err := proto.Marshal(nodebInfo)
+       if err != nil {
+               t.Errorf("#rNibWriter_test.TestUpdateNodebInfoOnConnectionStatusInversionSuccess - Failed to marshal NodeB entity. Error: %v", err)
+       }
+       var e error
+       var setExpected []interface{}
+
+       nodebNameKey := fmt.Sprintf("RAN:%s", inventoryName)
+       nodebIdKey := fmt.Sprintf("ENB:%s:%s", plmnId, nbId)
+       setExpected = append(setExpected, nodebNameKey, data)
+       setExpected = append(setExpected, nodebIdKey, data)
+
+       sdlInstanceMock.On("SetAndPublish", []string{channelName, eventName}, []interface{}{setExpected}).Return(e)
+
+       rNibErr := w.UpdateNodebInfoOnConnectionStatusInversion(nodebInfo, channelName, eventName)
+       assert.Nil(t, rNibErr)
+}
+
+func TestUpdateNodebInfoOnConnectionStatusInversionMissingInventoryNameFailure(t *testing.T) {
+       inventoryName := "name"
+       plmnId := "02f829"
+       nbId := "4a952a0a"
+       channelName := "RAN_CONNECT_STATE_CHANGE"
+       eventName := inventoryName + "_" + "CONNECTED"
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+       nodebInfo := &entities.NodebInfo{}
+       data, err := proto.Marshal(nodebInfo)
+       if err != nil {
+               t.Errorf("#rNibWriter_test.TestUpdateNodebInfoOnConnectionStatusInversionMissingInventoryNameFailure - Failed to marshal NodeB entity. Error: %v", err)
+       }
+       var e error
+       var setExpected []interface{}
+
+       nodebNameKey := fmt.Sprintf("RAN:%s", inventoryName)
+       nodebIdKey := fmt.Sprintf("ENB:%s:%s", plmnId, nbId)
+       setExpected = append(setExpected, nodebNameKey, data)
+       setExpected = append(setExpected, nodebIdKey, data)
+
+       sdlInstanceMock.On("SetAndPublish", []string{channelName, eventName}, []interface{}{setExpected}).Return(e)
+
+       rNibErr := w.UpdateNodebInfoOnConnectionStatusInversion(nodebInfo, channelName, eventName)
+
+       assert.NotNil(t, rNibErr)
+       assert.IsType(t, &common.ValidationError{}, rNibErr)
+}
+
+func TestUpdateNodebInfoOnConnectionStatusInversionMissingGlobalNbId(t *testing.T) {
+       inventoryName := "name"
+       channelName := "RAN_CONNECT_STATE_CHANGE"
+       eventName := inventoryName + "_" + "CONNECTED"
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+       nodebInfo := &entities.NodebInfo{}
+       nodebInfo.RanName = inventoryName
+       data, err := proto.Marshal(nodebInfo)
+       if err != nil {
+               t.Errorf("#rNibWriter_test.TestUpdateNodebInfoOnConnectionStatusInversionMissingInventoryNameFailure - Failed to marshal NodeB entity. Error: %v", err)
+       }
+       var e error
+       var setExpected []interface{}
+
+       nodebNameKey := fmt.Sprintf("RAN:%s", inventoryName)
+       setExpected = append(setExpected, nodebNameKey, data)
+       sdlInstanceMock.On("SetAndPublish", []string{channelName, eventName}, []interface{}{setExpected}).Return(e)
+
+       rNibErr := w.UpdateNodebInfoOnConnectionStatusInversion(nodebInfo, channelName, eventName)
+
+       assert.Nil(t, rNibErr)
+}
+
+func TestSaveGeneralConfiguration(t *testing.T) {
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+       key := common.BuildGeneralConfigurationKey()
+       configurationData := "{\"enableRic\":true}"
+       configuration := &entities.GeneralConfiguration{}
+       configuration.EnableRic = true
+
+       sdlInstanceMock.On("Set",[]interface{}{[]interface{}{key, []byte(configurationData)}}).Return(nil)
+       rNibErr := w.SaveGeneralConfiguration(configuration)
+
+       assert.Nil(t, rNibErr)
+       sdlInstanceMock.AssertExpectations(t)
+}
+
+func TestSaveGeneralConfigurationDbError(t *testing.T) {
+       w, sdlInstanceMock := initSdlInstanceMock(namespace)
+
+       key := common.BuildGeneralConfigurationKey()
+       configurationData := "{\"enableRic\":true}"
+       configuration := &entities.GeneralConfiguration{}
+       configuration.EnableRic = true
+
+       expectedErr := errors.New("expected error")
+
+       sdlInstanceMock.On("Set",[]interface{}{[]interface{}{key, []byte(configurationData)}}).Return(expectedErr)
+       rNibErr := w.SaveGeneralConfiguration(configuration)
+
+       assert.NotNil(t, rNibErr)
+}
+
 //Integration tests
 //
 //func TestSaveEnbGnbInteg(t *testing.T){
@@ -762,7 +869,7 @@ func TestRemoveE2TInstanceEmptyAddressFailure(t *testing.T) {
 //             nb.Configuration = &entities.NodebInfo_Enb{Enb:&enb}
 //             plmnId := 0x02f828
 //             nbId := 0x4a952a0a
-//             nbIdentity := &entities.NbIdentity{InventoryName: fmt.Sprintf("nameEnb%d" ,i), GlobalNbId:&entities.GlobalNbId{PlmnId:fmt.Sprintf("%02x", plmnId + i), NbId:fmt.Sprintf("%02x", nbId + i)}}
+//             nbIdentity := &entities.NbIdentity{InventoryName: fmt.Sprintf("nameEnb%d" ,i), GlobalNbId:&entities.GlobalNbId{RicId:fmt.Sprintf("%02x", plmnId + i), NbId:fmt.Sprintf("%02x", nbId + i)}}
 //             err := w.SaveNodeb(nbIdentity, &nb)
 //             if err != nil{
 //                     t.Errorf("#rNibWriter_test.TestSaveEnbInteg - Failed to save NodeB entity. Error: %v", err)
@@ -779,7 +886,7 @@ func TestRemoveE2TInstanceEmptyAddressFailure(t *testing.T) {
 //             gCell3 := &entities.ServedNRCell{ServedNrCellInformation:&entities.ServedNRCellInformation{CellId:fmt.Sprintf("%02x",3333 + i), NrPci:uint32(3 + i)}}
 //             gnb.ServedNrCells = []*entities.ServedNRCell{gCell1, gCell2, gCell3,}
 //             nb1.Configuration = &entities.NodebInfo_Gnb{Gnb:&gnb}
-//             nbIdentity = &entities.NbIdentity{InventoryName: fmt.Sprintf("nameGnb%d" ,i), GlobalNbId:&entities.GlobalNbId{PlmnId:fmt.Sprintf("%02x", plmnId - i), NbId:fmt.Sprintf("%02x", nbId - i)}}
+//             nbIdentity = &entities.NbIdentity{InventoryName: fmt.Sprintf("nameGnb%d" ,i), GlobalNbId:&entities.GlobalNbId{RicId:fmt.Sprintf("%02x", plmnId - i), NbId:fmt.Sprintf("%02x", nbId - i)}}
 //             err = w.SaveNodeb(nbIdentity, &nb1)
 //             if err != nil{
 //                     t.Errorf("#rNibWriter_test.TestSaveEnbInteg - Failed to save NodeB entity. Error: %v", err)
index d79565b..6beba8f 100644 (file)
@@ -15,5 +15,7 @@ keepAliveResponseTimeoutMs: 4500
 keepAliveDelayMs: 1500
 e2tInstanceDeletionTimeoutMs: 15000
 globalRicId:
-  plmnId: 131014
-  ricNearRtId: 556670
\ No newline at end of file
+  ricId: "AACCE"
+  mcc: "310"
+  mnc: "411"
+stateChangeMessageChannel: RAN_CONNECTION_STATUS_CHANGE
\ No newline at end of file
diff --git a/E2Manager/services/ran_alarm_service.go b/E2Manager/services/ran_alarm_service.go
new file mode 100644 (file)
index 0000000..046b183
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package services
+
+import (
+       "e2mgr/configuration"
+       "e2mgr/logger"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+)
+
+type ranAlarmServiceInstance struct {
+       logger *logger.Logger
+       config *configuration.Configuration
+}
+
+type RanAlarmService interface {
+       SetConnectivityChangeAlarm(nodebInfo *entities.NodebInfo) error
+}
+
+func NewRanAlarmService(logger *logger.Logger, config *configuration.Configuration) RanAlarmService {
+       return &ranAlarmServiceInstance{
+               logger: logger,
+               config: config,
+       }
+}
+
+func (m *ranAlarmServiceInstance) SetConnectivityChangeAlarm(nodebInfo *entities.NodebInfo) error {
+       m.logger.Infof("#ranAlarmServiceInstance.SetConnectivityChangeAlarm - RAN name: %s - Connectivity state was changed to %s", nodebInfo.RanName, nodebInfo.ConnectionStatus)
+       return nil
+}
index 7235028..dbc9e29 100644 (file)
@@ -49,23 +49,28 @@ type RNibDataService interface {
        RemoveE2TInstance(e2tAddress string) error
        UpdateGnbCells(nodebInfo *entities.NodebInfo, servedNrCells []*entities.ServedNRCell) error
        RemoveServedNrCells(inventoryName string, servedNrCells []*entities.ServedNRCell) error
+       GetGeneralConfiguration() (*entities.GeneralConfiguration, error)
+       UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, event string) error
+       SaveGeneralConfiguration(config *entities.GeneralConfiguration) error
 }
 
 type rNibDataService struct {
-       logger        *logger.Logger
-       rnibReader    reader.RNibReader
-       rnibWriter    rNibWriter.RNibWriter
-       maxAttempts   int
-       retryInterval time.Duration
+       logger                    *logger.Logger
+       rnibReader                reader.RNibReader
+       rnibWriter                rNibWriter.RNibWriter
+       maxAttempts               int
+       retryInterval             time.Duration
+       stateChangeMessageChannel string
 }
 
 func NewRnibDataService(logger *logger.Logger, config *configuration.Configuration, rnibReader reader.RNibReader, rnibWriter rNibWriter.RNibWriter) *rNibDataService {
        return &rNibDataService{
-               logger:        logger,
-               rnibReader:    rnibReader,
-               rnibWriter:    rnibWriter,
-               maxAttempts:   config.MaxRnibConnectionAttempts,
-               retryInterval: time.Duration(config.RnibRetryIntervalMs) * time.Millisecond,
+               logger:                    logger,
+               rnibReader:                rnibReader,
+               rnibWriter:                rnibWriter,
+               maxAttempts:               config.MaxRnibConnectionAttempts,
+               retryInterval:             time.Duration(config.RnibRetryIntervalMs) * time.Millisecond,
+               stateChangeMessageChannel: config.StateChangeMessageChannel,
        }
 }
 
@@ -269,6 +274,32 @@ func (w *rNibDataService) RemoveE2TInstance(e2tAddress string) error {
        return err
 }
 
+func (w *rNibDataService) GetGeneralConfiguration() (*entities.GeneralConfiguration, error) {
+       var generalConfiguration *entities.GeneralConfiguration = nil
+
+       err := w.retry("GetGeneralConfiguration", func() (err error) {
+               generalConfiguration, err = w.rnibReader.GetGeneralConfiguration()
+               return
+       })
+
+       if err == nil {
+               w.logger.Infof("#RnibDataService.GetGeneralConfiguration - enableRic: %t", generalConfiguration.EnableRic)
+       }
+
+       return generalConfiguration, err
+}
+
+func (w *rNibDataService) SaveGeneralConfiguration(config *entities.GeneralConfiguration) error {
+       w.logger.Infof("#RnibDataService.SaveGeneralConfiguration - configuration: %+v", *config)
+
+       err := w.retry("SaveGeneralConfiguration", func() (err error) {
+               err = w.rnibWriter.SaveGeneralConfiguration(config)
+               return
+       })
+
+       return err
+}
+
 func (w *rNibDataService) PingRnib() bool {
        err := w.retry("GetListNodebIds", func() (err error) {
                _, err = w.rnibReader.GetListNodebIds()
@@ -278,6 +309,17 @@ func (w *rNibDataService) PingRnib() bool {
        return !isRnibConnectionError(err)
 }
 
+func (w *rNibDataService) UpdateNodebInfoOnConnectionStatusInversion(nodebInfo *entities.NodebInfo, event string) error {
+       w.logger.Infof("#RnibDataService.UpdateNodebInfoOnConnectionStatusInversion - nodebInfo: %s", nodebInfo)
+
+       err := w.retry("UpdateNodebInfoOnConnectionStatusInversion", func() (err error) {
+               err = w.rnibWriter.UpdateNodebInfoOnConnectionStatusInversion(nodebInfo, w.stateChangeMessageChannel, event)
+               return
+       })
+
+       return err
+}
+
 func (w *rNibDataService) retry(rnibFunc string, f func() error) (err error) {
        attempts := w.maxAttempts
 
index ab67a32..f6529e3 100644 (file)
@@ -33,6 +33,8 @@ import (
        "testing"
 )
 
+const CHANNEL_NAME = "channel"
+
 func setupRnibDataServiceTest(t *testing.T) (*rNibDataService, *mocks.RnibReaderMock, *mocks.RnibWriterMock) {
        return setupRnibDataServiceTestWithMaxAttempts(t, 3)
 }
@@ -43,7 +45,7 @@ func setupRnibDataServiceTestWithMaxAttempts(t *testing.T, maxAttempts int) (*rN
                t.Errorf("#... - failed to initialize logger, error: %s", err)
        }
 
-       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: maxAttempts}
+       config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: maxAttempts, StateChangeMessageChannel: CHANNEL_NAME}
 
        readerMock := &mocks.RnibReaderMock{}
 
@@ -257,6 +259,29 @@ func TestPingRnibOkOtherError(t *testing.T) {
        assert.True(t, res)
 }
 
+func TestSuccessfulUpdateNodebInfoOnConnectionStatusInversion(t *testing.T) {
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
+       event := "event"
+
+       nodebInfo := &entities.NodebInfo{}
+       writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", nodebInfo, CHANNEL_NAME, event).Return(nil)
+
+       rnibDataService.UpdateNodebInfoOnConnectionStatusInversion(nodebInfo, event)
+       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfoOnConnectionStatusInversion", 1)
+}
+
+func TestConnFailureUpdateNodebInfoOnConnectionStatusInversion(t *testing.T) {
+       rnibDataService, _, writerMock := setupRnibDataServiceTest(t)
+       event := "event"
+
+       nodebInfo := &entities.NodebInfo{}
+       mockErr := &common.InternalError{Err: &net.OpError{Err: fmt.Errorf("connection error")}}
+       writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", nodebInfo, CHANNEL_NAME, event).Return(mockErr)
+
+       rnibDataService.UpdateNodebInfoOnConnectionStatusInversion(nodebInfo, event)
+       writerMock.AssertNumberOfCalls(t, "UpdateNodebInfoOnConnectionStatusInversion", 3)
+}
+
 //func TestConnFailureThenSuccessGetNodebIdList(t *testing.T) {
 //     rnibDataService, readerMock, _ := setupRnibDataServiceTest(t)
 //
index dfa637e..0adf3f9 100644 (file)
@@ -55,4 +55,4 @@ func GetHttpRequest() *http.Request {
        _ = json.NewEncoder(b).Encode(data)
        req, _ := http.NewRequest("POST", "https://localhost:3800/request", b)
        return req
-}
+}
\ No newline at end of file
index b947ae2..faf4fc2 100644 (file)
@@ -1,68 +1 @@
-<E2AP-PDU>\r
-    <initiatingMessage>\r
-        <procedureCode>1</procedureCode>\r
-        <criticality>\r
-            <reject/>\r
-        </criticality>\r
-        <value>\r
-            <E2setupRequest>\r
-                <protocolIEs>\r
-                    <E2setupRequestIEs>\r
-                        <id>3</id>\r
-                        <criticality>\r
-                            <reject/>\r
-                        </criticality>\r
-                        <value>\r
-                            <GlobalE2node-ID>\r
-                                <gNB>\r
-                                    <global-gNB-ID>\r
-                                        <plmn-id>13 10 14</plmn-id>\r
-                                        <gnb-id>\r
-                                            <gnb-ID>10011001101010101011</gnb-ID>\r
-                                        </gnb-id>\r
-                                    </global-gNB-ID>\r
-                                </gNB>\r
-                            </GlobalE2node-ID>\r
-                        </value>\r
-                    </E2setupRequestIEs>\r
-                    <E2setupRequestIEs>\r
-                        <id>10</id>\r
-                        <criticality>\r
-                            <reject/>\r
-                        </criticality>\r
-                        <value>\r
-                            <RANfunctions-List>\r
-                                <ProtocolIE-SingleContainer>\r
-                                    <id>8</id>\r
-                                    <criticality>\r
-                                        <reject/>\r
-                                    </criticality>\r
-                                    <value>\r
-                                        <RANfunction-Item>\r
-                                            <ranFunctionID>1</ranFunctionID>\r
-                                            <ranFunctionDefinition>334455</ranFunctionDefinition>\r
-                                            <ranFunctionRevision>0</ranFunctionRevision>\r
-                                        </RANfunction-Item>\r
-                                    </value>\r
-                                </ProtocolIE-SingleContainer>\r
-                                <ProtocolIE-SingleContainer>\r
-                                    <id>8</id>\r
-                                    <criticality>\r
-                                        <reject/>\r
-                                    </criticality>\r
-                                    <value>\r
-                                        <RANfunction-Item>\r
-                                            <ranFunctionID>7</ranFunctionID>\r
-                                            <ranFunctionDefinition>334455</ranFunctionDefinition>\r
-                                            <ranFunctionRevision>0</ranFunctionRevision>\r
-                                        </RANfunction-Item>\r
-                                    </value>\r
-                                </ProtocolIE-SingleContainer>\r
-                            </RANfunctions-List>\r
-                        </value>\r
-                    </E2setupRequestIEs>\r
-                </protocolIEs>\r
-            </E2setupRequest>\r
-        </value>\r
-    </initiatingMessage>\r
-</E2AP-PDU>
\ No newline at end of file
+<E2AP-PDU><initiatingMessage><procedureCode>1</procedureCode><criticality><reject /></criticality><value><E2setupRequest><protocolIEs><E2setupRequestIEs><id>3</id><criticality><reject /></criticality><value><GlobalE2node-ID><gNB><global-gNB-ID><plmn-id>02 F8 29</plmn-id><gnb-id><gnb-ID>                                                001100000011000000110000                                            </gnb-ID></gnb-id></global-gNB-ID></gNB></GlobalE2node-ID></value></E2setupRequestIEs><E2setupRequestIEs><id>10</id><criticality><reject /></criticality><value><RANfunctions-List><ProtocolIE-SingleContainer><id>8</id><criticality><ignore /></criticality><value><RANfunction-Item><ranFunctionID>1</ranFunctionID><ranFunctionDefinition><E2SM-gNB-NRT-RANfunction-Definition>    <ranFunction-Name>        <ranFunction-ShortName>gNB-X2</ranFunction-ShortName>        <ranFunction-E2SM-OID>1.3.6.1.4.1.28458.99.0.21.3.3.1.2</ranFunction-E2SM-OID>        <ranFunction-Description>gNB X2 Network Interface</ranFunction-Description>        <ranFunction-Instance>0</ranFunction-Instance>    </ranFunction-Name>    <ric-EventTriggerStyle-List>        <RIC-EventTriggerStyle-List>            <ric-EventTriggerStyle-Type>1</ric-EventTriggerStyle-Type>            <ric-EventTriggerStyle-Name>Message Type only</ric-EventTriggerStyle-Name>            <ric-EventTriggerFormat-Type>1</ric-EventTriggerFormat-Type>        </RIC-EventTriggerStyle-List>    </ric-EventTriggerStyle-List>    <ric-ReportStyle-List>        <RIC-ReportStyle-List>            <ric-ReportStyle-Type>1</ric-ReportStyle-Type>            <ric-ReportStyle-Name>Complete message</ric-ReportStyle-Name>            <ric-ReportActionFormat-Type>1</ric-ReportActionFormat-Type>            <ric-ReportRanParameterDef-List>                <RANparameterDef-Item>                    <ranParameter-ID>1</ranParameter-ID>                    <ranParameter-Name>AddTimestamp</ranParameter-Name>                    <ranParameter-Type><boolean/></ranParameter-Type>                </RANparameterDef-Item>            </ric-ReportRanParameterDef-List>            <ric-IndicationHeaderFormat-Type>1</ric-IndicationHeaderFormat-Type>            <ric-IndicationMessageFormat-Type>1</ric-IndicationMessageFormat-Type>        </RIC-ReportStyle-List>    </ric-ReportStyle-List>    <ric-InsertStyle-List>        <RIC-InsertStyle-List>            <ric-InsertStyle-Type>1</ric-InsertStyle-Type>            <ric-InsertStyle-Name>Complete message</ric-InsertStyle-Name>            <ric-InsertActionFormat-Type>1</ric-InsertActionFormat-Type>            <ric-InsertRanParameterDef-List>                <RANparameterDef-Item>                    <ranParameter-ID>1</ranParameter-ID>                    <ranParameter-Name>AddTimestamp</ranParameter-Name>                    <ranParameter-Type><boolean/></ranParameter-Type>                </RANparameterDef-Item>            </ric-InsertRanParameterDef-List>            <ric-IndicationHeaderFormat-Type>1</ric-IndicationHeaderFormat-Type>            <ric-IndicationMessageFormat-Type>1</ric-IndicationMessageFormat-Type>            <ric-CallProcessIDFormat-Type>1</ric-CallProcessIDFormat-Type>        </RIC-InsertStyle-List>    </ric-InsertStyle-List>    <ric-ControlStyle-List>        <RIC-ControlStyle-List>            <ric-ControlStyle-Type>1</ric-ControlStyle-Type>            <ric-ControlStyle-Name>Complete message</ric-ControlStyle-Name>            <ric-ControlHeaderFormat-Type>1</ric-ControlHeaderFormat-Type>            <ric-ControlMessageFormat-Type>1</ric-ControlMessageFormat-Type>            <ric-CallProcessIDFormat-Type>1</ric-CallProcessIDFormat-Type>        </RIC-ControlStyle-List>    </ric-ControlStyle-List></E2SM-gNB-NRT-RANfunction-Definition></ranFunctionDefinition><ranFunctionRevision>1</ranFunctionRevision></RANfunction-Item></value></ProtocolIE-SingleContainer><ProtocolIE-SingleContainer><id>8</id><criticality><ignore /></criticality><value><RANfunction-Item><ranFunctionID>2</ranFunctionID><ranFunctionDefinition><E2SM-gNB-NRT-RANfunction-Definition>    <ranFunction-Name>        <ranFunction-ShortName>gNB-NRT</ranFunction-ShortName>        <ranFunction-E2SM-OID>1.3.6.1.4.1.28458.99.0.21.3.3.3.3</ranFunction-E2SM-OID>        <ranFunction-Description>gNB Neighbour Relation Table</ranFunction-Description>    </ranFunction-Name>    <ric-EventTriggerStyle-List>        <RIC-EventTriggerStyle-List>            <ric-EventTriggerStyle-Type>1</ric-EventTriggerStyle-Type>            <ric-EventTriggerStyle-Name>Notification</ric-EventTriggerStyle-Name>            <ric-EventTriggerFormat-Type>1</ric-EventTriggerFormat-Type>        </RIC-EventTriggerStyle-List>    </ric-EventTriggerStyle-List>    <ric-ReportStyle-List>        <RIC-ReportStyle-List>            <ric-ReportStyle-Type>1</ric-ReportStyle-Type>            <ric-ReportStyle-Name>Complete table</ric-ReportStyle-Name>            <ric-ReportActionFormat-Type>1</ric-ReportActionFormat-Type>            <ric-ReportRanParameterDef-List>                <RANparameterDef-Item>                    <ranParameter-ID>1</ranParameter-ID>                    <ranParameter-Name>AddTimestamp</ranParameter-Name>                    <ranParameter-Type><boolean/></ranParameter-Type>                </RANparameterDef-Item>            </ric-ReportRanParameterDef-List>            <ric-IndicationHeaderFormat-Type>1</ric-IndicationHeaderFormat-Type>            <ric-IndicationMessageFormat-Type>1</ric-IndicationMessageFormat-Type>        </RIC-ReportStyle-List>    </ric-ReportStyle-List>    <ric-ControlStyle-List>        <RIC-ControlStyle-List>            <ric-ControlStyle-Type>1</ric-ControlStyle-Type>            <ric-ControlStyle-Name>NRT modification</ric-ControlStyle-Name>            <ric-ControlHeaderFormat-Type>1</ric-ControlHeaderFormat-Type>            <ric-ControlMessageFormat-Type>1</ric-ControlMessageFormat-Type>            <ric-CallProcessIDFormat-Type>0</ric-CallProcessIDFormat-Type>        </RIC-ControlStyle-List>    </ric-ControlStyle-List></E2SM-gNB-NRT-RANfunction-Definition></ranFunctionDefinition><ranFunctionRevision>1</ranFunctionRevision></RANfunction-Item></value></ProtocolIE-SingleContainer><ProtocolIE-SingleContainer><id>8</id><criticality><ignore /></criticality><value><RANfunction-Item><ranFunctionID>3</ranFunctionID><ranFunctionDefinition><E2SM-gNB-NRT-RANfunction-Definition>    <ranFunction-Name>        <ranFunction-ShortName>gNB-X2</ranFunction-ShortName>        <ranFunction-E2SM-OID>1.3.6.1.4.1.28458.99.0.21.3.3.1.2</ranFunction-E2SM-OID>        <ranFunction-Description>gNB X2 Network Interface</ranFunction-Description>        <ranFunction-Instance>1</ranFunction-Instance>    </ranFunction-Name>    <ric-EventTriggerStyle-List>        <RIC-EventTriggerStyle-List>            <ric-EventTriggerStyle-Type>1</ric-EventTriggerStyle-Type>            <ric-EventTriggerStyle-Name>Message Type only</ric-EventTriggerStyle-Name>            <ric-EventTriggerFormat-Type>1</ric-EventTriggerFormat-Type>        </RIC-EventTriggerStyle-List>    </ric-EventTriggerStyle-List>    <ric-PolicyStyle-List>        <RIC-PolicyStyle-List>            <ric-PolicyStyle-Type>1</ric-PolicyStyle-Type>            <ric-PolicyStyle-Name>Message Admission</ric-PolicyStyle-Name>            <ric-PolicyActionFormat-Type>2</ric-PolicyActionFormat-Type>            <ric-PolicyRanParameterDef-List>                <RANparameterDef-Item>                    <ranParameter-ID>1</ranParameter-ID>                    <ranParameter-Name>QCI1</ranParameter-Name>                    <ranParameter-Type><integer/></ranParameter-Type>                </RANparameterDef-Item>                <RANparameterDef-Item>                    <ranParameter-ID>2</ranParameter-ID>                    <ranParameter-Name>ARP1</ranParameter-Name>                    <ranParameter-Type><integer/></ranParameter-Type>                </RANparameterDef-Item>                <RANparameterDef-Item>                    <ranParameter-ID>3</ranParameter-ID>                    <ranParameter-Name>SPID</ranParameter-Name>                    <ranParameter-Type><integer/></ranParameter-Type>                </RANparameterDef-Item>                <RANparameterDef-Item>                    <ranParameter-ID>4</ranParameter-ID>                    <ranParameter-Name>U-TEID1</ranParameter-Name>                    <ranParameter-Type><octet-string/></ranParameter-Type>                </RANparameterDef-Item>                <RANparameterDef-Item>                    <ranParameter-ID>10</ranParameter-ID>                    <ranParameter-Name>Load_offset</ranParameter-Name>                    <ranParameter-Type><integer/></ranParameter-Type>                </RANparameterDef-Item>            </ric-PolicyRanParameterDef-List>        </RIC-PolicyStyle-List>    </ric-PolicyStyle-List></E2SM-gNB-NRT-RANfunction-Definition></ranFunctionDefinition><ranFunctionRevision>1</ranFunctionRevision></RANfunction-Item></value></ProtocolIE-SingleContainer></RANfunctions-List></value></E2setupRequestIEs></protocolIEs></E2setupRequest></value></initiatingMessage></E2AP-PDU>
\ No newline at end of file