First commit

This commit is contained in:
Leonardo Bonati
2021-12-08 20:17:46 +00:00
commit 60dffad583
2923 changed files with 463894 additions and 0 deletions

View File

@@ -0,0 +1,273 @@
//
// 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 rmrmsghandlers
import (
"bytes"
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"encoding/xml"
"errors"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"strconv"
"strings"
)
type E2SetupRequestNotificationHandler struct {
logger *logger.Logger
config *configuration.Configuration
e2tInstancesManager managers.IE2TInstancesManager
rmrSender *rmrsender.RmrSender
rNibDataService services.RNibDataService
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{
logger: logger,
config: config,
e2tInstancesManager: e2tInstancesManager,
rmrSender: rmrSender,
rNibDataService: rNibDataService,
e2tAssociationManager: e2tAssociationManager,
}
}
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)
setupRequest, e2tIpAddress, err := h.parseSetupRequest(request.Payload)
if err != nil {
h.logger.Errorf(err.Error())
return
}
h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - E2T Address: %s - handling E2_SETUP_REQUEST", e2tIpAddress)
h.logger.Debugf("#E2SetupRequestNotificationHandler.Handle - E2_SETUP_REQUEST has been parsed successfully %+v", setupRequest)
_, err = h.e2tInstancesManager.GetE2TInstance(e2tIpAddress)
if err != nil {
h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err)
return
}
nodebInfo, err := h.rNibDataService.GetNodeb(ranName)
if err != nil {
if _, ok := err.(*common.ResourceNotFoundError); !ok {
h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
return
}
if nodebInfo, err = h.handleNewRan(ranName, e2tIpAddress, setupRequest); err != nil {
return
}
} else {
if err = h.handleExistingRan(ranName, nodebInfo, setupRequest); err != nil {
return
}
}
err = h.e2tAssociationManager.AssociateRan(e2tIpAddress, nodebInfo)
if err != nil {
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)
}
return
}
h.handleSuccessfulResponse(ranName, request, setupRequest)
}
func (h E2SetupRequestNotificationHandler) handleNewRan(ranName string, e2tIpAddress string, setupRequest *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
nodebInfo, err := h.buildNodebInfo(ranName, e2tIpAddress, setupRequest)
if err != nil {
h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed to build nodebInfo entity. Error: %s", ranName, err)
return nil, err
}
nbIdentity := h.buildNbIdentity(ranName, setupRequest)
err = h.rNibDataService.SaveNodeb(nbIdentity, nodebInfo)
if err != nil {
h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed to save nodebInfo entity. Error: %s", ranName, err)
return nil, err
}
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
}
if ranFunctions != nil {
nodebInfo.GetGnb().RanFunctions = ranFunctions
}
return nil
}
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")
}
err := h.setGnbFunctions(nodebInfo, setupRequest)
return err
}
func (h E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(nodebInfo *entities.NodebInfo, req *models.NotificationRequest) {
failureResponse := models.NewE2SetupFailureResponseMessage(models.TimeToWaitEnum.V60s)
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)
}
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.rmrSender.WhSend(msg)
}
func (h E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName string, req *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage) {
ricNearRtId, err := convertTo20BitString(h.config.GlobalRicId.RicNearRtId)
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)
h.logger.Debugf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", successResponse)
responsePayload, err := xml.Marshal(&successResponse.E2APPDU)
if err != nil {
h.logger.Warnf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
}
responsePayload = replaceEmptyTagsWithSelfClosing(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 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))
return []byte(responseString)
}
func convertTo20BitString(ricNearRtId string) (string, error) {
r, err := strconv.ParseUint(ricNearRtId, 16, 32)
if err != nil {
return "", err
}
return fmt.Sprintf("%020b", r)[:20], nil
}
func (h E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*models.E2SetupRequestMessage, string, error) {
pipInd := bytes.IndexByte(payload, '|')
if pipInd < 0 {
return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found")
}
e2tIpAddress := string(payload[:pipInd])
if len(e2tIpAddress) == 0 {
return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Empty E2T Address received")
}
h.logger.Infof("#E2SetupRequestNotificationHandler.parseSetupRequest - payload: %s", payload[pipInd+1:])
setupRequest := &models.E2SetupRequestMessage{}
err := xml.Unmarshal(payload[pipInd+1:], &setupRequest.E2APPDU)
if err != nil {
return nil, "", errors.New(fmt.Sprintf("#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: %x", payload))
}
return setupRequest, e2tIpAddress, nil
}
func (h E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAddress string, request *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
var err error
nodebInfo := &entities.NodebInfo{
AssociatedE2TInstanceAddress: e2tAddress,
ConnectionStatus: entities.ConnectionStatus_CONNECTED,
RanName: ranName,
NodeType: entities.Node_GNB,
Configuration: &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{}},
GlobalNbId: h.buildGlobalNbId(request),
}
err = h.setGnbFunctions(nodebInfo, request)
return nodebInfo, err
}
func (h E2SetupRequestNotificationHandler) buildGlobalNbId(setupRequest *models.E2SetupRequestMessage) *entities.GlobalNbId {
return &entities.GlobalNbId{
PlmnId: setupRequest.GetPlmnId(),
NbId: setupRequest.GetNbId(),
}
}
func (h E2SetupRequestNotificationHandler) buildNbIdentity(ranName string, setupRequest *models.E2SetupRequestMessage) *entities.NbIdentity {
return &entities.NbIdentity{
InventoryName: ranName,
GlobalNbId: h.buildGlobalNbId(setupRequest),
}
}

View File

@@ -0,0 +1,417 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/configuration"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/tests"
"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/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"io/ioutil"
"path/filepath"
"testing"
)
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"
)
func readXmlFile(t *testing.T, xmlPath string) []byte {
path, err := filepath.Abs(xmlPath)
if err != nil {
t.Fatal(err)
}
xmlAsBytes, err := ioutil.ReadFile(path)
if err != nil {
t.Fatal(err)
}
return xmlAsBytes
}
func TestParseGnbSetupRequest_Success(t *testing.T) {
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
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.Nil(t, err)
}
func TestParseEnGnbSetupRequest_Success(t *testing.T) {
enGnbXml := readXmlFile(t, EnGnbSetupRequestXmlPath)
handler, _, _, _, _, _ := initMocks(t)
prefBytes := []byte(prefix)
request, _, err := handler.parseSetupRequest(append(prefBytes, enGnbXml...))
assert.Equal(t, "131014", request.GetPlmnId())
assert.Equal(t, "11000101110001101100011111111000", request.GetNbId())
assert.Nil(t, err)
}
func TestParseNgEnbSetupRequest_Success(t *testing.T) {
ngEnbXml := readXmlFile(t, NgEnbSetupRequestXmlPath)
handler, _, _, _, _, _ := initMocks(t)
prefBytes := []byte(prefix)
request, _, err := handler.parseSetupRequest(append(prefBytes, ngEnbXml...))
assert.Equal(t, "131014", request.GetPlmnId())
assert.Equal(t, "101010101010101010", request.GetNbId())
assert.Nil(t, err)
}
func TestParseEnbSetupRequest_Success(t *testing.T) {
enbXml := readXmlFile(t, EnbSetupRequestXmlPath)
handler, _, _, _, _, _ := initMocks(t)
prefBytes := []byte(prefix)
request, _, err := handler.parseSetupRequest(append(prefBytes, enbXml...))
assert.Equal(t, "6359AB", request.GetPlmnId())
assert.Equal(t, "101010101010101010", request.GetNbId())
assert.Nil(t, err)
}
func TestParseSetupRequest_PipFailure(t *testing.T) {
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
handler, _, _, _, _, _ := initMocks(t)
prefBytes := []byte("10.0.2.15:9999")
request, _, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...))
assert.Nil(t, request)
assert.NotNil(t, err)
assert.EqualError(t, err, "#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found")
}
func TestParseSetupRequest_UnmarshalFailure(t *testing.T) {
handler, _, _, _, _, _ := initMocks(t)
prefBytes := []byte(prefix)
request, _, err := handler.parseSetupRequest(append(prefBytes, 1, 2, 3))
assert.Nil(t, request)
assert.NotNil(t, err)
assert.EqualError(t, err, "#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: 31302e302e322e31353a393939397c010203")
}
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)
var gnb *entities.NodebInfo
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).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)
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)
var gnb *entities.NodebInfo
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).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)
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)
var gnb *entities.NodebInfo
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).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, xmlEnGnb...)}
handler.Handle(notificationRequest)
assertNewNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
}
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)
var gnb *entities.NodebInfo
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).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, xmlNgEnb...)}
handler.Handle(notificationRequest)
assertNewNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
}
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)
var gnb = &entities.NodebInfo{
RanName: nodebRanName,
AssociatedE2TInstanceAddress: e2tInstanceFullAddress,
ConnectionStatus: entities.ConnectionStatus_CONNECTED,
NodeType: entities.Node_GNB,
Configuration: &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{}},
}
readerMock.On("GetNodeb", mock.Anything).Return(gnb, 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)
assertExistingNodebSuccessCalls(readerMock, t, e2tInstancesManagerMock, writerMock, routingManagerClientMock, rmrMessengerMock)
}
func TestE2SetupRequestNotificationHandler_HandleParseError(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...)}
handler.Handle(notificationRequest)
readerMock.AssertNotCalled(t, "GetNodeb", mock.Anything)
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
}
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"...)}
handler.Handle(notificationRequest)
readerMock.AssertNotCalled(t, "GetNodeb", mock.Anything)
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
}
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"))
prefBytes := []byte(prefix)
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
handler.Handle(notificationRequest)
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
readerMock.AssertNotCalled(t, "GetNodeb", mock.Anything)
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
}
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)
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...)}
handler.Handle(notificationRequest)
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
}
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)
var gnb *entities.NodebInfo
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
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...)}
handler.Handle(notificationRequest)
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
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)
}
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"}}
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
routingManagerClientMock := &mocks.RoutingManagerClientMock{}
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
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)
var gnb *entities.NodebInfo
readerMock.On("GetNodeb", mock.Anything).Return(gnb, common.NewResourceNotFoundError("Not found"))
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).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, xmlEnGnb...)}
handler.Handle(notificationRequest)
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
routingManagerClientMock.AssertCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
writerMock.AssertCalled(t, "UpdateNodebInfo", mock.Anything)
e2tInstancesManagerMock.AssertCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
}
func TestE2SetupRequestNotificationHandler_HandleExistingGnbInvalidStatusError(t *testing.T) {
xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath)
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)
prefBytes := []byte(prefix)
notificationRequest := &models.NotificationRequest{RanName: nodebRanName, Payload: append(prefBytes, xmlGnb...)}
handler.Handle(notificationRequest)
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
routingManagerClientMock.AssertNotCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
writerMock.AssertNotCalled(t, "UpdateNodebInfo", mock.Anything)
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
}
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"}}
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
routingManagerClientMock := &mocks.RoutingManagerClientMock{}
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock)
handler := NewE2SetupRequestNotificationHandler(logger, config, e2tInstancesManagerMock, rmrSender, rnibDataService, e2tAssociationManager)
return handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock
}
func assertNewNodebSuccessCalls(readerMock *mocks.RnibReaderMock, t *testing.T, e2tInstancesManagerMock *mocks.E2TInstancesManagerMock, writerMock *mocks.RnibWriterMock, routingManagerClientMock *mocks.RoutingManagerClientMock, rmrMessengerMock *mocks.RmrMessengerMock) {
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
routingManagerClientMock.AssertCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
writerMock.AssertCalled(t, "UpdateNodebInfo", mock.Anything)
e2tInstancesManagerMock.AssertCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
rmrMessengerMock.AssertCalled(t, "SendMsg", mock.Anything, mock.Anything)
}
func assertExistingNodebSuccessCalls(readerMock *mocks.RnibReaderMock, t *testing.T, e2tInstancesManagerMock *mocks.E2TInstancesManagerMock, writerMock *mocks.RnibWriterMock, routingManagerClientMock *mocks.RoutingManagerClientMock, rmrMessengerMock *mocks.RmrMessengerMock) {
readerMock.AssertCalled(t, "GetNodeb", mock.Anything)
writerMock.AssertNotCalled(t, "SaveNodeb", mock.Anything, mock.Anything)
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceFullAddress)
routingManagerClientMock.AssertCalled(t, "AssociateRanToE2TInstance", e2tInstanceFullAddress, mock.Anything)
writerMock.AssertCalled(t, "UpdateNodebInfo", mock.Anything)
e2tInstancesManagerMock.AssertCalled(t, "AddRansToInstance", mock.Anything, mock.Anything)
rmrMessengerMock.AssertCalled(t, "SendMsg", mock.Anything, mock.Anything)
}

View File

@@ -0,0 +1,118 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/clients"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"encoding/json"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
)
type E2TermInitNotificationHandler struct {
logger *logger.Logger
ranDisconnectionManager *managers.RanDisconnectionManager
e2tInstancesManager managers.IE2TInstancesManager
routingManagerClient clients.IRoutingManagerClient
}
func NewE2TermInitNotificationHandler(logger *logger.Logger, ranDisconnectionManager *managers.RanDisconnectionManager, e2tInstancesManager managers.IE2TInstancesManager, routingManagerClient clients.IRoutingManagerClient) E2TermInitNotificationHandler {
return E2TermInitNotificationHandler{
logger: logger,
ranDisconnectionManager: ranDisconnectionManager,
e2tInstancesManager: e2tInstancesManager,
routingManagerClient: routingManagerClient,
}
}
func (h E2TermInitNotificationHandler) Handle(request *models.NotificationRequest) {
unmarshalledPayload := models.E2TermInitPayload{}
err := json.Unmarshal(request.Payload, &unmarshalledPayload)
if err != nil {
h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Error unmarshaling E2 Term Init payload: %s", err)
return
}
e2tAddress := unmarshalledPayload.Address
if len(e2tAddress) == 0 {
h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Empty E2T address received")
return
}
h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T payload: %s - handling E2_TERM_INIT", unmarshalledPayload)
e2tInstance, err := h.e2tInstancesManager.GetE2TInstance(e2tAddress)
if err != nil {
_, ok := err.(*common.ResourceNotFoundError)
if !ok {
h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err)
return
}
h.HandleNewE2TInstance(e2tAddress, unmarshalledPayload.PodName)
return
}
if len(e2tInstance.AssociatedRanList) == 0 {
h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T Address: %s - E2T instance has no associated RANs", e2tInstance.Address)
return
}
if e2tInstance.State == entities.ToBeDeleted{
h.logger.Infof("#E2TermInitNotificationHandler.Handle - E2T Address: %s - E2T instance status is: %s, ignore", e2tInstance.Address, e2tInstance.State)
return
}
h.HandleExistingE2TInstance(e2tInstance)
h.logger.Infof("#E2TermInitNotificationHandler.Handle - Completed handling of E2_TERM_INIT")
}
func (h E2TermInitNotificationHandler) HandleExistingE2TInstance(e2tInstance *entities.E2TInstance) {
for _, ranName := range e2tInstance.AssociatedRanList {
if err := h.ranDisconnectionManager.DisconnectRan(ranName); err != nil {
if _, ok := err.(*common.ResourceNotFoundError); !ok{
break
}
}
}
}
func (h E2TermInitNotificationHandler) HandleNewE2TInstance(e2tAddress string, podName string) {
err := h.routingManagerClient.AddE2TInstance(e2tAddress)
if err != nil{
h.logger.Errorf("#E2TermInitNotificationHandler.HandleNewE2TInstance - e2t address: %s - routing manager failure", e2tAddress)
return
}
_ = h.e2tInstancesManager.AddE2TInstance(e2tAddress, podName)
}

View File

@@ -0,0 +1,478 @@
//
// 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 rmrmsghandlers
import (
"bytes"
"e2mgr/clients"
"e2mgr/configuration"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"e2mgr/tests"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/mock"
"io/ioutil"
"net/http"
"testing"
)
const (
e2tInitPayload = "{\"address\":\"10.0.2.15\", \"fqdn\":\"\"}"
e2tInstanceAddress = "10.0.2.15"
podName = "podNAme_test"
)
func initRanLostConnectionTest(t *testing.T) (*logger.Logger, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock) {
logger := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
routingManagerClientMock := &mocks.RoutingManagerClientMock{}
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock)
ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager)
handler := NewE2TermInitNotificationHandler(logger, ranDisconnectionManager, e2tInstancesManagerMock, routingManagerClientMock)
return logger, handler, readerMock, writerMock, e2tInstancesManagerMock, routingManagerClientMock
}
func initRanLostConnectionTestWithRealE2tInstanceManager(t *testing.T) (*logger.Logger, *configuration.Configuration, E2TermInitNotificationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
logger := initLog(t)
config := configuration.ParseConfiguration()
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
httpClientMock := &mocks.HttpClientMock{}
routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClientMock)
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient)
ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager)
handler := NewE2TermInitNotificationHandler(logger, ranDisconnectionManager, e2tInstancesManager, routingManagerClient)
return logger, config, handler, readerMock, writerMock, httpClientMock
}
func TestE2TermInitUnmarshalPayloadFailure(t *testing.T) {
_, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("asd")}
handler.Handle(notificationRequest)
e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance")
e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
}
func TestE2TermInitEmptyE2TAddress(t *testing.T) {
_, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("{\"address\":\"\"}")}
handler.Handle(notificationRequest)
e2tInstancesManagerMock.AssertNotCalled(t, "GetE2TInstance")
e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
}
func TestE2TermInitGetE2TInstanceFailure(t *testing.T) {
_, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
var e2tInstance *entities.E2TInstance
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error")))
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
e2tInstancesManagerMock.AssertNotCalled(t, "AddE2TInstance")
}
func TestE2TermInitGetE2TInstanceDbFailure(t *testing.T) {
_, _, handler, readerMock, writerMock, _ := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var e2tInstance *entities.E2TInstance
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewInternalError(fmt.Errorf("internal error")))
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
}
func TestE2TermInitNewE2TInstance(t *testing.T) {
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var e2tInstance *entities.E2TInstance
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found"))
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
url := config.RoutingManager.BaseUrl + clients.AddE2TInstanceApiSuffix
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
e2tAddresses := []string{}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, common.NewResourceNotFoundError(""))
e2tAddresses = append(e2tAddresses, e2tInstanceAddress)
writerMock.On("SaveE2TAddresses", e2tAddresses).Return(nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
httpClientMock.AssertCalled(t, "Post", url, mock.Anything, mock.Anything)
writerMock.AssertCalled(t, "SaveE2TInstance", mock.Anything)
writerMock.AssertCalled(t, "SaveE2TAddresses", e2tAddresses)
}
func TestE2TermInitNewE2TInstance__RoutingManagerError(t *testing.T) {
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var e2tInstance *entities.E2TInstance
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, common.NewResourceNotFoundError("not found"))
url := config.RoutingManager.BaseUrl + clients.AddE2TInstanceApiSuffix
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{}, errors.New("error"))
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 0)
}
func TestE2TermInitExistingE2TInstanceNoAssociatedRans(t *testing.T) {
_, handler, _, _, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
e2tInstancesManagerMock.AssertCalled(t, "GetE2TInstance", e2tInstanceAddress)
}
func TestE2TermInitHandlerSuccessOneRan(t *testing.T) {
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var rnibErr error
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
var disconnectedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", RanName).Return(disconnectedNodeb, rnibErr)
var updatedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
writerMock.On("UpdateNodebInfo", updatedNodeb).Return(rnibErr)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
httpClientMock.AssertNumberOfCalls(t, "Post", 1)
}
func TestE2TermInitHandlerSuccessOneRan_RoutingManagerError(t *testing.T) {
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var rnibErr error
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
var disconnectedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", RanName).Return(disconnectedNodeb, rnibErr)
var updatedNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
writerMock.On("UpdateNodebInfo", updatedNodeb).Return(rnibErr)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{}, errors.New("error"))
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
httpClientMock.AssertNumberOfCalls(t, "Post", 1)
}
func TestE2TermInitHandlerSuccessOneRanShuttingdown(t *testing.T) {
_, _, handler, readerMock, writerMock, _ := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var rnibErr error
var initialNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
var argNodeb = &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
}
func TestE2TermInitHandlerSuccessOneRan_ToBeDeleted(t *testing.T) {
_, _, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var rnibErr error
var initialNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
readerMock.On("GetNodeb", RanName).Return(initialNodeb, rnibErr)
var argNodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
writerMock.On("UpdateNodebInfo", argNodeb).Return(rnibErr)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.State = entities.ToBeDeleted
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
httpClientMock.AssertNotCalled(t, "Post", mock.Anything, mock.Anything, mock.Anything)
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
}
func TestE2TermInitHandlerSuccessTwoRans(t *testing.T) {
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var rnibErr error
test2 := "test2"
//First RAN
var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
var disconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", RanName).Return(firstRan, rnibErr).Return(disconnectedFirstRan, rnibErr)
var updatedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
writerMock.On("UpdateNodebInfo", updatedFirstRan).Return(rnibErr)
var updatedDisconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
writerMock.On("UpdateNodebInfo", updatedDisconnectedFirstRan).Return(rnibErr)
//Second RAN
var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
var disconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr).Return(disconnectedSecondRan, rnibErr)
var updatedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
writerMock.On("UpdateNodebInfo", updatedSecondRan).Return(rnibErr)
var updatedDisconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: ""}
writerMock.On("UpdateNodebInfo", updatedDisconnectedSecondRan).Return(rnibErr)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 4)
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 2)
httpClientMock.AssertNumberOfCalls(t, "Post", 2)
}
func TestE2TermInitHandlerSuccessTwoRansSecondRanShutdown(t *testing.T) {
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var rnibErr error
test2 := "test2"
//First RAN
var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
var disconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", RanName).Return(firstRan, rnibErr).Return(disconnectedFirstRan, rnibErr)
var updatedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
writerMock.On("UpdateNodebInfo", updatedFirstRan).Return(rnibErr)
var updatedDisconnectedFirstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: ""}
writerMock.On("UpdateNodebInfo", updatedDisconnectedFirstRan).Return(rnibErr)
//Second RAN
var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
httpClientMock.AssertNumberOfCalls(t, "Post", 1)
}
func TestE2TermInitHandlerSuccessTwoRansFirstNotFoundFailure(t *testing.T) {
_, config, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
var rnibErr error
test2 := "test2"
//First RAN
var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", RanName).Return(firstRan, common.NewResourceNotFoundError("not found"))
//Second RAN
var secondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
var disconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", test2).Return(secondRan, rnibErr).Return(disconnectedSecondRan, rnibErr)
var updatedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: "10.0.2.15"}
writerMock.On("UpdateNodebInfo", updatedSecondRan).Return(rnibErr)
var updatedDisconnectedSecondRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, RanName: test2, AssociatedE2TInstanceAddress: ""}
writerMock.On("UpdateNodebInfo", updatedDisconnectedSecondRan).Return(rnibErr)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
url := config.RoutingManager.BaseUrl + clients.DissociateRanE2TInstanceApiSuffix
httpClientMock.On("Post", url, mock.Anything, mock.Anything).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 1)
httpClientMock.AssertNumberOfCalls(t, "Post", 1)
}
func TestE2TermInitHandlerSuccessTwoRansFirstRnibInternalErrorFailure(t *testing.T) {
_, _, handler, readerMock, writerMock, httpClientMock := initRanLostConnectionTestWithRealE2tInstanceManager(t)
test2 := "test2"
//First RAN
var firstRan = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED, RanName: RanName, AssociatedE2TInstanceAddress: "10.0.2.15"}
readerMock.On("GetNodeb", RanName).Return(firstRan, common.NewInternalError(fmt.Errorf("internal error")))
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, test2)
readerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil).Return(e2tInstance, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 0)
writerMock.AssertNumberOfCalls(t, "SaveE2TInstance", 0)
httpClientMock.AssertNumberOfCalls(t, "Post", 0)
}
func TestE2TermInitHandlerSuccessZeroRans(t *testing.T) {
_, handler, _, writerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
}
func TestE2TermInitHandlerFailureGetNodebInternalError(t *testing.T) {
_, handler, readerMock, writerMock, e2tInstancesManagerMock, _ := initRanLostConnectionTest(t)
var nodebInfo *entities.NodebInfo
readerMock.On("GetNodeb", "test1").Return(nodebInfo, common.NewInternalError(fmt.Errorf("internal error")))
e2tInstance := entities.NewE2TInstance(e2tInstanceAddress, podName)
e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, "test1")
e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceAddress).Return(e2tInstance, nil)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(e2tInitPayload)}
handler.Handle(notificationRequest)
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
}
// TODO: extract to test_utils
func initRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
return rmrsender.NewRmrSender(log, rmrMessenger)
}
// TODO: extract to test_utils
func initLog(t *testing.T) *logger.Logger {
log, err := logger.InitLogger(logger.InfoLevel)
if err != nil {
t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
}
return log
}

View File

@@ -0,0 +1,55 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"e2mgr/services"
"encoding/json"
)
type E2TKeepAliveResponseHandler struct {
logger *logger.Logger
rnibDataService services.RNibDataService
e2TInstancesManager managers.IE2TInstancesManager
}
func NewE2TKeepAliveResponseHandler(logger *logger.Logger, rnibDataService services.RNibDataService, e2TInstancesManager managers.IE2TInstancesManager) E2TKeepAliveResponseHandler {
return E2TKeepAliveResponseHandler{
logger: logger,
rnibDataService: rnibDataService,
e2TInstancesManager: e2TInstancesManager,
}
}
func (h E2TKeepAliveResponseHandler) Handle(request *models.NotificationRequest) {
unmarshalledPayload := models.E2TKeepAlivePayload{}
err := json.Unmarshal(request.Payload, &unmarshalledPayload)
if err != nil {
h.logger.Errorf("#E2TKeepAliveResponseHandler.Handle - Error unmarshaling RMR request payload: %v", err)
return
}
_ = h.e2TInstancesManager.ResetKeepAliveTimestamp(unmarshalledPayload.Address)
}

View File

@@ -0,0 +1,63 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/configuration"
"e2mgr/logger"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/services"
"testing"
)
func initE2TKeepAliveTest(t *testing.T) (*logger.Logger, E2TKeepAliveResponseHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.E2TInstancesManagerMock) {
logger := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
handler := NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManagerMock)
return logger, handler, readerMock, writerMock, e2tInstancesManagerMock
}
func TestE2TKeepAliveUnmarshalPayloadFailure(t *testing.T) {
_, handler, _, _, e2tInstancesManagerMock := initE2TKeepAliveTest(t)
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte("asd")}
handler.Handle(notificationRequest)
e2tInstancesManagerMock.AssertNotCalled(t, "ResetKeepAliveTimestamp")
}
func TestE2TKeepAliveUnmarshalPayloadSuccess(t *testing.T) {
_, handler, _, _, e2tInstancesManagerMock := initE2TKeepAliveTest(t)
jsonRequest := "{\"address\":\"10.10.2.15:9800\"}"
notificationRequest := &models.NotificationRequest{RanName: RanName, Payload: []byte(jsonRequest)}
e2tInstancesManagerMock.On("ResetKeepAliveTimestamp", "10.10.2.15:9800").Return(nil)
handler.Handle(notificationRequest)
e2tInstancesManagerMock.AssertCalled(t, "ResetKeepAliveTimestamp", "10.10.2.15:9800")
}

View File

@@ -0,0 +1,81 @@
//
// 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 rmrmsghandlers
/*import (
"e2mgr/converters"
"e2mgr/e2pdus"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"time"
)
type EnbLoadInformationNotificationHandler struct {
logger *logger.Logger
rnibDataService services.RNibDataService
//extractor converters.IEnbLoadInformationExtractor
}
func NewEnbLoadInformationNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, extractor converters.IEnbLoadInformationExtractor) EnbLoadInformationNotificationHandler {
return EnbLoadInformationNotificationHandler{
logger: logger,
rnibDataService: rnibDataService,
extractor: extractor,
}
}
func elapsed(startTime time.Time) float64 {
return float64(time.Since(startTime)) / float64(time.Millisecond)
}
func (h EnbLoadInformationNotificationHandler) Handle(request *models.NotificationRequest) {
pdu, err := converters.UnpackX2apPdu(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
if err != nil {
h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Unpack failed. Error: %v", request.RanName, err)
return
}
h.logger.Debugf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Unpacked message successfully", request.RanName)
ranLoadInformation := &entities.RanLoadInformation{LoadTimestamp: uint64(request.StartTime.UnixNano())}
err = h.extractor.ExtractAndBuildRanLoadInformation(pdu, ranLoadInformation)
if err != nil {
h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed at ExtractAndBuildRanLoadInformation. Error: %v", request.RanName, err)
return
}
h.logger.Debugf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Successfully done with extracting and building RAN load information. elapsed: %f ms", request.RanName, elapsed(request.StartTime))
rnibErr := h.rnibDataService.SaveRanLoadInformation(request.RanName, ranLoadInformation)
if rnibErr != nil {
h.logger.Errorf("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Failed saving RAN load information. Error: %v", request.RanName, rnibErr)
return
}
h.logger.Infof("#EnbLoadInformationNotificationHandler.Handle - RAN name: %s - Successfully saved RAN load information to RNIB. elapsed: %f ms", request.RanName, elapsed(request.StartTime))
}*/

View File

@@ -0,0 +1,144 @@
//
// 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 rmrmsghandlers
/*import (
"e2mgr/models"
"fmt"
"time"
)
const (
FullUperPdu string = "004c07080004001980da0100075bde017c148003d5a8205000017c180003d5a875555403331420000012883a0003547400cd20002801ea16007c1f07c1f107c1f0781e007c80800031a02c000c88199040a00352083669190000d8908020000be0c4001ead4016e007ab50100002f8320067ab5005b8c1ead5070190c00001d637805f220000f56a081400005f020000f56a1d555400ccc508002801ea16007c1f07c1f107c1f0781e007c80800031a02c000c88199040a00352083669190000d8908020000be044001ead4016e007ab50100002f8120067ab5005b8c1ead5070190c00000"
FullAperPdu string = "" // TODO: populate and use it
BasicUperPdu string = "004898000400190d0000074200017c148003d5a80000"
BasicAperPdu string = "" // TODO: populate and use it
GarbagePdu string = "12312312"
)
func createNotificationRequest(ranName string, transactionId []byte, packedPdu string) (*models.NotificationRequest, error) {
var packedByteSlice []byte
_, err := fmt.Sscanf(packedPdu, "%x", &packedByteSlice)
if err != nil {
return nil, err
}
return models.NewNotificationRequest(ranName, packedByteSlice, time.Now(), transactionId, nil), nil
}
func createNotificationRequestAndHandle(ranName string, transactionId []byte, loadInformationHandler EnbLoadInformationNotificationHandler, pdu string) error {
notificationRequest, err := createNotificationRequest(ranName, transactionId, pdu)
if err != nil {
return err
}
loadInformationHandler.Handle(notificationRequest)
return nil
}*/
//func TestLoadInformationHandlerSuccess(t *testing.T) {
// log, err := logger.InitLogger(logger.InfoLevel)
// if err != nil {
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerSuccess - failed to initialize logger, error: %v", err)
// }
//
// inventoryName := "testRan"
//
// writerMock := &mocks.RnibWriterMock{}
// rnibWriterProvider := func() rNibWriter.RNibWriter {
// return writerMock
// }
//
// var rnibErr error
// writerMock.On("SaveRanLoadInformation",inventoryName, mock.Anything).Return(rnibErr)
//
// loadInformationHandler := NewEnbLoadInformationNotificationHandler(rnibWriterProvider)
//
// var packedExampleByteSlice []byte
// _, err = fmt.Sscanf(FullUperPdu, "%x", &packedExampleByteSlice)
// notificationRequest := models.NewNotificationRequest(inventoryName, packedExampleByteSlice, time.Now(), " 881828026419")
// loadInformationHandler.Handle(log, notificationRequest)
//
// writerMock.AssertNumberOfCalls(t, "SaveRanLoadInformation", 1)
//}
//
//func TestLoadInformationHandlerPayloadFailure(t *testing.T) {
// log, err := logger.InitLogger(logger.InfoLevel)
// if err != nil {
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerPayloadFailure - failed to initialize logger, error: %v", err)
// }
//
// inventoryName := "testRan"
//
// writerMock := &mocks.RnibWriterMock{}
// rnibWriterProvider := func() rNibWriter.RNibWriter {
// return writerMock
// }
//
// var rnibErr error
// writerMock.On("SaveRanLoadInformation",inventoryName, mock.Anything).Return(rnibErr)
//
// loadInformationHandler := NewEnbLoadInformationNotificationHandler(rnibWriterProvider)
//
// var packedExampleByteSlice []byte
// _, err = fmt.Sscanf(GarbagePdu, "%x", &packedExampleByteSlice)
// notificationRequest := models.NewNotificationRequest(inventoryName, packedExampleByteSlice, time.Now(), " 881828026419")
// loadInformationHandler.Handle(log, notificationRequest)
//
// writerMock.AssertNumberOfCalls(t, "SaveRanLoadInformation", 0)
//}
// Integration test
//func TestLoadInformationHandlerOverrideSuccess(t *testing.T) {
// log, err := logger.InitLogger(logger.InfoLevel)
// if err != nil {
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - failed to initialize logger, error: %s", err)
// }
//
// rNibWriter.Init("e2Manager", 1)
// defer rNibWriter.Close()
// reader.Init("e2Manager", 1)
// defer reader.Close()
// loadInformationHandler := NewEnbLoadInformationNotificationHandler(rNibWriter.GetRNibWriter)
//
// err = createNotificationRequestAndHandle("ranName", " 881828026419", loadInformationHandler, FullUperPdu)
//
// if err != nil {
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - failed creating NotificationRequest, error: %v", err)
// }
//
// err = createNotificationRequestAndHandle("ranName", " 881828026419", loadInformationHandler, BasicUperPdu)
//
// if err != nil {
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - failed creating NotificationRequest, error: %v", err)
// }
//
// ranLoadInformation, rnibErr := reader.GetRNibReader().GetRanLoadInformation("ranName")
//
// if (rnibErr != nil) {
// t.Errorf("#setup_request_handler_test.TestLoadInformationHandlerOverrideSuccess - RNIB error: %v", err)
// }
//
// assert.Len(t, ranLoadInformation.CellLoadInfos, 1)
//}

View File

@@ -0,0 +1,70 @@
//
// 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 rmrmsghandlers
// #cgo CFLAGS: -I../../3rdparty/asn1codec/inc/ -I../../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../../3rdparty/asn1codec/lib/ -L../../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <configuration_update_wrapper.h>
import "C"
import (
"e2mgr/converters"
"e2mgr/e2pdus"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services/rmrsender"
"e2mgr/utils"
)
type EndcConfigurationUpdateHandler struct {
logger *logger.Logger
rmrSender *rmrsender.RmrSender
}
func NewEndcConfigurationUpdateHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender) EndcConfigurationUpdateHandler {
return EndcConfigurationUpdateHandler{
logger: logger,
rmrSender: rmrSender,
}
}
func (h EndcConfigurationUpdateHandler) Handle(request *models.NotificationRequest) {
refinedMessage, err := converters.UnpackX2apPduAndRefine(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize /*allocation buffer*/, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
if err != nil {
h.logger.Errorf("#endc_configuration_update_handler.Handle - unpack failed. Error: %v", err)
msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, request.RanName, e2pdus.PackedEndcConfigurationUpdateFailure, request.TransactionId, request.GetMsgSrc())
_ = h.rmrSender.Send(msg)
h.logger.Infof("#EndcConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling endc configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
return
}
h.logger.Infof("#endc_configuration_update_handler.Handle - Endc configuration update initiating message received")
h.logger.Debugf("#endc_configuration_update_handler.Handle - Endc configuration update initiating message payload: %s", refinedMessage.PduPrint)
msg := models.NewRmrMessage(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, request.RanName, e2pdus.PackedEndcConfigurationUpdateAck, request.TransactionId, request.GetMsgSrc())
_ = h.rmrSender.Send(msg)
h.logger.Infof("#EndcConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling endc configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
}

View File

@@ -0,0 +1,78 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"fmt"
"testing"
"time"
"unsafe"
)
const PackedEndcConfigurationUpdateAck = "2025000a00000100f70003000000"
const PackedEndcConfigurationUpdateFailure = "402500080000010005400142"
func initEndcConfigurationUpdateHandlerTest(t *testing.T) (EndcConfigurationUpdateHandler, *mocks.RmrMessengerMock) {
log := initLog(t)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := initRmrSender(rmrMessengerMock, log)
h := NewEndcConfigurationUpdateHandler(log, rmrSender)
return h, rmrMessengerMock
}
func TestHandleEndcConfigUpdateSuccess(t *testing.T) {
h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
ranName := "test"
xAction := []byte("123456aa")
var payload []byte
_, _ = fmt.Sscanf(PackedEndcConfigurationUpdateAck, "%x", &payload)
var msgSrc unsafe.Pointer
mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_ACK, len(payload), ranName, &payload, &xAction, msgSrc)
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now(),
TransactionId: *mBuf.XAction}
var err error
rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, err)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
}
func TestHandleEndcConfigUpdateFailure(t *testing.T) {
h, rmrMessengerMock := initEndcConfigurationUpdateHandlerTest(t)
ranName := "test"
xAction := []byte("123456aa")
var payload []byte
_, _ = fmt.Sscanf(PackedEndcConfigurationUpdateFailure, "%x", &payload)
var msgSrc unsafe.Pointer
mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_CONF_UPDATE_FAILURE, len(payload), ranName, &payload, &xAction, msgSrc)
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0}, StartTime: time.Now(),
TransactionId: *mBuf.XAction}
rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
h.Handle(&notificationRequest)
rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
}

View File

@@ -0,0 +1,29 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package rmrmsghandlers
import (
"e2mgr/models"
)
type NotificationHandler interface {
Handle(*models.NotificationRequest)
}

View File

@@ -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 rmrmsghandlers
import (
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
)
type RanLostConnectionHandler struct {
ranDisconnectionManager managers.IRanDisconnectionManager
logger *logger.Logger
}
func NewRanLostConnectionHandler(logger *logger.Logger, ranDisconnectionManager managers.IRanDisconnectionManager) RanLostConnectionHandler {
return RanLostConnectionHandler{
logger: logger,
ranDisconnectionManager: ranDisconnectionManager,
}
}
func (h RanLostConnectionHandler) Handle(request *models.NotificationRequest) {
ranName := request.RanName
h.logger.Warnf("#RanLostConnectionHandler.Handle - RAN name: %s - Received lost connection notification", ranName)
_ = h.ranDisconnectionManager.DisconnectRan(ranName)
}

View File

@@ -0,0 +1,133 @@
//// 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 rmrmsghandlers
import (
"bytes"
"e2mgr/clients"
"e2mgr/configuration"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/services"
"encoding/json"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"io/ioutil"
"net/http"
"testing"
)
const ranName = "test"
const e2tAddress = "10.10.2.15:9800"
func TestLostConnectionHandlerSuccess(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
notificationRequest := models.NotificationRequest{RanName: ranName}
ranDisconnectionManagerMock := &mocks.RanDisconnectionManagerMock{}
ranDisconnectionManagerMock.On("DisconnectRan", ranName).Return(nil)
handler := NewRanLostConnectionHandler(logger, ranDisconnectionManagerMock)
handler.Handle(&notificationRequest)
ranDisconnectionManagerMock.AssertCalled(t, "DisconnectRan", ranName)
}
func TestLostConnectionHandlerFailure(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
notificationRequest := models.NotificationRequest{RanName: ranName}
ranDisconnectionManagerMock := &mocks.RanDisconnectionManagerMock{}
ranDisconnectionManagerMock.On("DisconnectRan", ranName).Return(errors.New("error"))
handler := NewRanLostConnectionHandler(logger, ranDisconnectionManagerMock)
handler.Handle(&notificationRequest)
ranDisconnectionManagerMock.AssertCalled(t, "DisconnectRan", ranName)
}
func setupLostConnectionHandlerTestWithRealDisconnectionManager(t *testing.T, isSuccessfulHttpPost bool) (RanLostConnectionHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
logger, _ := logger.InitLogger(logger.InfoLevel)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
httpClientMock := &mocks.HttpClientMock{}
routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClientMock)
e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient)
ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager)
handler := NewRanLostConnectionHandler(logger, ranDisconnectionManager)
origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: e2tAddress}
var rnibErr error
readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
updatedNodebInfo1 := *origNodebInfo
updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
writerMock.On("UpdateNodebInfo", &updatedNodebInfo1).Return(rnibErr)
updatedNodebInfo2 := *origNodebInfo
updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
writerMock.On("UpdateNodebInfo", &updatedNodebInfo2).Return(rnibErr)
e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList: []string{ranName}}
readerMock.On("GetE2TInstance", e2tAddress).Return(e2tInstance, nil)
e2tInstanceToSave := *e2tInstance
e2tInstanceToSave.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
mockHttpClient(httpClientMock, isSuccessfulHttpPost)
return handler, readerMock, writerMock, httpClientMock
}
func mockHttpClient(httpClientMock *mocks.HttpClientMock, isSuccessful bool) {
data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(e2tAddress, RanName)}
marshaled, _ := json.Marshal(data)
body := bytes.NewBuffer(marshaled)
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
var respStatusCode int
if isSuccessful {
respStatusCode = http.StatusCreated
} else {
respStatusCode = http.StatusBadRequest
}
httpClientMock.On("Post", clients.DissociateRanE2TInstanceApiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
}
func TestLostConnectionHandlerFailureWithRealDisconnectionManager(t *testing.T) {
handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealDisconnectionManager(t, false)
notificationRequest := models.NotificationRequest{RanName: ranName}
handler.Handle(&notificationRequest)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
httpClientMock.AssertExpectations(t)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
}
func TestLostConnectionHandlerSuccessWithRealDisconnectionManager(t *testing.T) {
handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTestWithRealDisconnectionManager(t, true)
notificationRequest := models.NotificationRequest{RanName: ranName}
handler.Handle(&notificationRequest)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
httpClientMock.AssertExpectations(t)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
}

View File

@@ -0,0 +1,106 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/enums"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/utils"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
)
type SetupResponseNotificationHandler struct {
logger *logger.Logger
rnibDataService services.RNibDataService
setupResponseManager managers.ISetupResponseManager
ranStatusChangeManager managers.IRanStatusChangeManager
msgType int
}
var msgTypeToMsgName = map[int]string{
rmrCgo.RIC_X2_SETUP_RESP: "X2 Setup Response",
rmrCgo.RIC_X2_SETUP_FAILURE: "X2 Setup Failure Response",
rmrCgo.RIC_ENDC_X2_SETUP_RESP: "ENDC Setup Response",
rmrCgo.RIC_ENDC_X2_SETUP_FAILURE: "ENDC Setup Failure Response",
}
func NewSetupResponseNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, setupResponseManager managers.ISetupResponseManager, ranStatusChangeManager managers.IRanStatusChangeManager, msgType int) SetupResponseNotificationHandler {
return SetupResponseNotificationHandler{
logger: logger,
rnibDataService: rnibDataService,
setupResponseManager: setupResponseManager,
ranStatusChangeManager: ranStatusChangeManager,
msgType: msgType,
}
}
func (h SetupResponseNotificationHandler) Handle(request *models.NotificationRequest) {
msgName := msgTypeToMsgName[h.msgType]
h.logger.Infof("#SetupResponseNotificationHandler - RAN name: %s - Received %s notification", request.RanName, msgName)
inventoryName := request.RanName
nodebInfo, rnibErr := h.rnibDataService.GetNodeb(inventoryName)
if rnibErr != nil {
h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Error fetching RAN from rNib: %v", request.RanName, rnibErr)
return
}
if !isConnectionStatusValid(nodebInfo.ConnectionStatus) {
h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Invalid RAN connection status: %s", request.RanName, nodebInfo.ConnectionStatus)
return
}
nbIdentity := &entities.NbIdentity{InventoryName: inventoryName}
err := h.setupResponseManager.PopulateNodebByPdu(h.logger, nbIdentity, nodebInfo, request.Payload)
if err != nil {
return
}
rnibErr = h.rnibDataService.SaveNodeb(nbIdentity, nodebInfo)
if rnibErr != nil {
h.logger.Errorf("#SetupResponseNotificationHandler - RAN name: %s - Error saving RAN to rNib: %v", request.RanName, rnibErr)
return
}
h.logger.Infof("#SetupResponseNotificationHandler - RAN name: %s - Successfully saved RAN to rNib", request.RanName)
h.logger.Infof("#SetupResponseNotificationHandler - Summary: elapsed time for receiving and handling setup response message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
if !isSuccessSetupResponseMessage(h.msgType) {
return
}
_ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_CONNECTED, enums.RIC_TO_RAN, nodebInfo)
}
func isConnectionStatusValid(connectionStatus entities.ConnectionStatus) bool {
return connectionStatus == entities.ConnectionStatus_CONNECTING || connectionStatus == entities.ConnectionStatus_CONNECTED
}
func isSuccessSetupResponseMessage(msgType int) bool {
return msgType == rmrCgo.RIC_X2_SETUP_RESP || msgType == rmrCgo.RIC_ENDC_X2_SETUP_RESP
}

View File

@@ -0,0 +1,339 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/configuration"
"e2mgr/converters"
"e2mgr/e2managererrors"
"e2mgr/enums"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"encoding/json"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"testing"
"unsafe"
)
const (
RanName = "test"
X2SetupResponsePackedPdu = "2006002a000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"
EndcSetupResponsePackedPdu = "202400808e00000100f600808640000200fc00090002f829504a952a0a00fd007200010c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a000211e148033e4e5e4c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a00021a0044033e4e5e000000002c001e3f271f2e3d4ff0031e3f274400010000150400000a00020000"
X2SetupFailureResponsePackedPdu = "4006001a0000030005400200000016400100001140087821a00000008040"
EndcSetupFailureResponsePackedPdu = "4024001a0000030005400200000016400100001140087821a00000008040"
)
type setupSuccessResponseTestCase struct {
packedPdu string
setupResponseManager managers.ISetupResponseManager
msgType int
saveNodebMockError error
sendMsgError error
statusChangeMbuf *rmrCgo.MBuf
}
type setupFailureResponseTestCase struct {
packedPdu string
setupResponseManager managers.ISetupResponseManager
msgType int
saveNodebMockError error
}
type setupResponseTestContext struct {
logger *logger.Logger
readerMock *mocks.RnibReaderMock
writerMock *mocks.RnibWriterMock
rnibDataService services.RNibDataService
setupResponseManager managers.ISetupResponseManager
ranStatusChangeManager managers.IRanStatusChangeManager
rmrSender *rmrsender.RmrSender
rmrMessengerMock *mocks.RmrMessengerMock
}
func NewSetupResponseTestContext(manager managers.ISetupResponseManager) *setupResponseTestContext {
logger, _ := logger.InitLogger(logger.InfoLevel)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := initRmrSender(rmrMessengerMock, logger)
ranStatusChangeManager := managers.NewRanStatusChangeManager(logger, rmrSender)
return &setupResponseTestContext{
logger: logger,
readerMock: readerMock,
writerMock: writerMock,
rnibDataService: rnibDataService,
setupResponseManager: manager,
ranStatusChangeManager: ranStatusChangeManager,
rmrMessengerMock: rmrMessengerMock,
rmrSender: rmrSender,
}
}
func TestSetupResponseGetNodebFailure(t *testing.T) {
notificationRequest := models.NotificationRequest{RanName: RanName}
testContext := NewSetupResponseTestContext(nil)
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, &managers.X2SetupResponseManager{}, testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
testContext.readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewInternalError(errors.New("Error")))
handler.Handle(&notificationRequest)
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestSetupResponseInvalidConnectionStatus(t *testing.T) {
ranName := "test"
notificationRequest := models.NotificationRequest{RanName: ranName}
testContext := NewSetupResponseTestContext(nil)
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, &managers.X2SetupResponseManager{}, testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
var rnibErr error
testContext.readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}, rnibErr)
handler.Handle(&notificationRequest)
testContext.readerMock.AssertCalled(t, "GetNodeb", ranName)
testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func executeHandleSetupSuccessResponse(t *testing.T, tc setupSuccessResponseTestCase) (*setupResponseTestContext, *entities.NodebInfo) {
var payload []byte
_, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
if err != nil {
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
}
notificationRequest := models.NotificationRequest{RanName: RanName, Payload: payload}
testContext := NewSetupResponseTestContext(tc.setupResponseManager)
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, testContext.setupResponseManager, testContext.ranStatusChangeManager, tc.msgType)
var rnibErr error
nodebInfo := &entities.NodebInfo{
ConnectionStatus: entities.ConnectionStatus_CONNECTING,
RanName: RanName,
Ip: "10.0.2.2",
Port: 1231,
}
testContext.readerMock.On("GetNodeb", RanName).Return(nodebInfo, rnibErr)
testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(tc.saveNodebMockError)
testContext.rmrMessengerMock.On("SendMsg", tc.statusChangeMbuf, true).Return(&rmrCgo.MBuf{}, tc.sendMsgError)
handler.Handle(&notificationRequest)
return testContext, nodebInfo
}
func getRanConnectedMbuf(nodeType entities.Node_Type) *rmrCgo.MBuf {
var xAction []byte
resourceStatusPayload := models.NewResourceStatusPayload(nodeType, enums.RIC_TO_RAN)
resourceStatusJson, _ := json.Marshal(resourceStatusPayload)
var msgSrc unsafe.Pointer
return rmrCgo.NewMBuf(rmrCgo.RAN_CONNECTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xAction, msgSrc)
}
func executeHandleSetupFailureResponse(t *testing.T, tc setupFailureResponseTestCase) (*setupResponseTestContext, *entities.NodebInfo) {
var payload []byte
_, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
if err != nil {
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
}
notificationRequest := models.NotificationRequest{RanName: RanName, Payload: payload}
testContext := NewSetupResponseTestContext(tc.setupResponseManager)
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, testContext.setupResponseManager, testContext.ranStatusChangeManager, tc.msgType)
var rnibErr error
nodebInfo := &entities.NodebInfo{
ConnectionStatus: entities.ConnectionStatus_CONNECTING,
RanName: RanName,
Ip: "10.0.2.2",
Port: 1231,
}
testContext.readerMock.On("GetNodeb", RanName).Return(nodebInfo, rnibErr)
testContext.writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(tc.saveNodebMockError)
handler.Handle(&notificationRequest)
return testContext, nodebInfo
}
func TestX2SetupResponse(t *testing.T) {
logger := initLog(t)
var saveNodebMockError error
var sendMsgError error
tc := setupSuccessResponseTestCase{
X2SetupResponsePackedPdu,
managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
rmrCgo.RIC_X2_SETUP_RESP,
saveNodebMockError,
sendMsgError,
getRanConnectedMbuf(entities.Node_ENB),
}
testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
assert.EqualValues(t, entities.Node_ENB, nodebInfo.NodeType)
assert.IsType(t, &entities.NodebInfo_Enb{}, nodebInfo.Configuration)
i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
assert.NotNil(t, i.Enb)
testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
}
func TestX2SetupFailureResponse(t *testing.T) {
logger := initLog(t)
var saveNodebMockError error
tc := setupFailureResponseTestCase{
X2SetupFailureResponsePackedPdu,
managers.NewX2SetupFailureResponseManager(converters.NewX2SetupFailureResponseConverter(logger)),
rmrCgo.RIC_X2_SETUP_FAILURE,
saveNodebMockError,
}
testContext, nodebInfo := executeHandleSetupFailureResponse(t, tc)
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
assert.EqualValues(t, entities.Failure_X2_SETUP_FAILURE, nodebInfo.FailureType)
assert.NotNil(t, nodebInfo.SetupFailure)
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestEndcSetupResponse(t *testing.T) {
logger := initLog(t)
var saveNodebMockError error
var sendMsgError error
tc := setupSuccessResponseTestCase{
EndcSetupResponsePackedPdu,
managers.NewEndcSetupResponseManager(converters.NewEndcSetupResponseConverter(logger)),
rmrCgo.RIC_ENDC_X2_SETUP_RESP,
saveNodebMockError,
sendMsgError,
getRanConnectedMbuf(entities.Node_GNB),
}
testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
assert.EqualValues(t, entities.Node_GNB, nodebInfo.NodeType)
assert.IsType(t, &entities.NodebInfo_Gnb{}, nodebInfo.Configuration)
i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Gnb)
assert.NotNil(t, i.Gnb)
testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
}
func TestEndcSetupFailureResponse(t *testing.T) {
logger := initLog(t)
var saveNodebMockError error
tc := setupFailureResponseTestCase{
EndcSetupFailureResponsePackedPdu,
managers.NewEndcSetupFailureResponseManager(converters.NewEndcSetupFailureResponseConverter(logger)),
rmrCgo.RIC_ENDC_X2_SETUP_FAILURE,
saveNodebMockError,
}
testContext, nodebInfo := executeHandleSetupFailureResponse(t, tc)
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED_SETUP_FAILED, nodebInfo.ConnectionStatus)
assert.EqualValues(t, entities.Failure_ENDC_X2_SETUP_FAILURE, nodebInfo.FailureType)
assert.NotNil(t, nodebInfo.SetupFailure)
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestSetupResponseInvalidPayload(t *testing.T) {
logger := initLog(t)
ranName := "test"
notificationRequest := models.NotificationRequest{RanName: ranName, Payload: []byte("123")}
testContext := NewSetupResponseTestContext(nil)
handler := NewSetupResponseNotificationHandler(testContext.logger, testContext.rnibDataService, managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)), testContext.ranStatusChangeManager, rmrCgo.RIC_X2_SETUP_RESP)
var rnibErr error
testContext.readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTING}, rnibErr)
handler.Handle(&notificationRequest)
testContext.readerMock.AssertCalled(t, "GetNodeb", ranName)
testContext.writerMock.AssertNotCalled(t, "SaveNodeb")
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestSetupResponseSaveNodebFailure(t *testing.T) {
logger := initLog(t)
saveNodebMockError := common.NewInternalError(errors.New("Error"))
var sendMsgError error
tc := setupSuccessResponseTestCase{
X2SetupResponsePackedPdu,
managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
rmrCgo.RIC_X2_SETUP_RESP,
saveNodebMockError,
sendMsgError,
getRanConnectedMbuf(entities.Node_ENB),
}
testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
testContext.rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestSetupResponseStatusChangeSendFailure(t *testing.T) {
logger := initLog(t)
var saveNodebMockError error
sendMsgError := e2managererrors.NewRmrError()
tc := setupSuccessResponseTestCase{
X2SetupResponsePackedPdu,
managers.NewX2SetupResponseManager(converters.NewX2SetupResponseConverter(logger)),
rmrCgo.RIC_X2_SETUP_RESP,
saveNodebMockError,
sendMsgError,
getRanConnectedMbuf(entities.Node_ENB),
}
testContext, nodebInfo := executeHandleSetupSuccessResponse(t, tc)
testContext.readerMock.AssertCalled(t, "GetNodeb", RanName)
testContext.writerMock.AssertCalled(t, "SaveNodeb", mock.Anything, nodebInfo)
assert.EqualValues(t, entities.ConnectionStatus_CONNECTED, nodebInfo.ConnectionStatus)
assert.EqualValues(t, entities.Node_ENB, nodebInfo.NodeType)
assert.IsType(t, &entities.NodebInfo_Enb{}, nodebInfo.Configuration)
i, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
assert.NotNil(t, i.Enb)
testContext.rmrMessengerMock.AssertCalled(t, "SendMsg", tc.statusChangeMbuf, true)
}

View File

@@ -0,0 +1,87 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package rmrmsghandlers
// #cgo CFLAGS: -I../../3rdparty/asn1codec/inc/ -I../../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../../3rdparty/asn1codec/lib/ -L../../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <x2reset_response_wrapper.h>
import "C"
import (
"e2mgr/e2pdus"
"e2mgr/enums"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"e2mgr/utils"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
)
type X2ResetRequestNotificationHandler struct {
logger *logger.Logger
rnibDataService services.RNibDataService
ranStatusChangeManager managers.IRanStatusChangeManager
rmrSender *rmrsender.RmrSender
}
func NewX2ResetRequestNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, ranStatusChangeManager managers.IRanStatusChangeManager, rmrSender *rmrsender.RmrSender) X2ResetRequestNotificationHandler {
return X2ResetRequestNotificationHandler{
logger: logger,
rnibDataService: rnibDataService,
ranStatusChangeManager: ranStatusChangeManager,
rmrSender: rmrSender,
}
}
func (h X2ResetRequestNotificationHandler) Handle(request *models.NotificationRequest) {
h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Ran name: %s", request.RanName)
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))
return
}
h.logger.Debugf("#X2ResetRequestNotificationHandler.Handle - nodeB entity retrieved. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
if nb.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
h.logger.Warnf("#X2ResetRequestNotificationHandler.Handle - nodeB entity in incorrect state. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
return
}
if nb.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
h.logger.Errorf("#X2ResetRequestNotificationHandler.Handle - nodeB entity in incorrect state. RanName %s, ConnectionStatus %s", nb.RanName, nb.ConnectionStatus)
h.logger.Infof("#X2ResetRequestNotificationHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
return
}
msg := 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.ranStatusChangeManager.Execute(rmrCgo.RAN_RESTARTED, enums.RAN_TO_RIC, nb)
}

View File

@@ -0,0 +1,132 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/configuration"
"e2mgr/e2pdus"
"e2mgr/enums"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/tests"
"encoding/json"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"testing"
"time"
"unsafe"
)
func initX2ResetRequestNotificationHandlerTest(t *testing.T) (X2ResetRequestNotificationHandler, *mocks.RnibReaderMock, *mocks.RmrMessengerMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := initRmrSender(rmrMessengerMock, log)
ranStatusChangeManager := managers.NewRanStatusChangeManager(log, rmrSender)
h := NewX2ResetRequestNotificationHandler(log, rnibDataService, ranStatusChangeManager, rmrSender)
return h, readerMock, rmrMessengerMock
}
func getRanRestartedMbuf(nodeType entities.Node_Type, messageDirection enums.MessageDirection) *rmrCgo.MBuf {
var xAction []byte
resourceStatusPayload := models.NewResourceStatusPayload(nodeType, messageDirection)
resourceStatusJson, _ := json.Marshal(resourceStatusPayload)
var msgSrc unsafe.Pointer
return rmrCgo.NewMBuf(rmrCgo.RAN_RESTARTED, len(resourceStatusJson), RanName, &resourceStatusJson, &xAction, msgSrc)
}
func TestHandleX2ResetRequestNotificationSuccess(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
ranName := "test"
xAction := []byte("123456aa")
notificationRequest := models.NewNotificationRequest(ranName, []byte{}, time.Now(), xAction, nil)
nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
var err error
readerMock.On("GetNodeb", ranName).Return(nb, err)
var msgSrc unsafe.Pointer
resetResponseMbuf := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET_RESP, len(e2pdus.PackedX2ResetResponse), ranName, &e2pdus.PackedX2ResetResponse, &xAction, msgSrc)
rmrMessengerMock.On("SendMsg", resetResponseMbuf, true).Return(&rmrCgo.MBuf{}, err)
ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RAN_TO_RIC)
rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
h.Handle(notificationRequest)
rmrMessengerMock.AssertCalled(t, "SendMsg", resetResponseMbuf, true)
rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
}
func TestHandleX2ResetRequestNotificationShuttingDownStatus(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
var payload []byte
xAction := []byte("123456aa")
var msgSrc unsafe.Pointer
mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction, msgSrc)
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
StartTime: time.Now(), TransactionId: xAction}
nb := &entities.NodebInfo{RanName: mBuf.Meid, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
var rnibErr error
readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestHandleX2ResetRequestNotificationDisconnectStatus(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
var payload []byte
xAction := []byte("123456aa")
var msgSrc unsafe.Pointer
mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction, msgSrc)
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload, StartTime: time.Now(), TransactionId: xAction}
nb := &entities.NodebInfo{RanName: mBuf.Meid, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
var rnibErr error
readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestHandleX2ResetRequestNotificationGetNodebFailed(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetRequestNotificationHandlerTest(t)
var payload []byte
var xAction []byte
var msgSrc unsafe.Pointer
mBuf := rmrCgo.NewMBuf(tests.MessageType, len(payload), "RanName", &payload, &xAction, msgSrc)
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
StartTime: time.Now(), TransactionId: xAction}
var nb *entities.NodebInfo
rnibErr := &common.ResourceNotFoundError{}
readerMock.On("GetNodeb", mBuf.Meid).Return(nb, rnibErr)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}

View File

@@ -0,0 +1,104 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package rmrmsghandlers
// #cgo CFLAGS: -I../../3rdparty/asn1codec/inc/ -I../../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../../3rdparty/asn1codec/lib/ -L../../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
import "C"
import (
"e2mgr/converters"
"e2mgr/enums"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/utils"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
)
type X2ResetResponseHandler struct {
logger *logger.Logger
rnibDataService services.RNibDataService
ranStatusChangeManager managers.IRanStatusChangeManager
extractor converters.IX2ResetResponseExtractor
}
func NewX2ResetResponseHandler(logger *logger.Logger, rnibDataService services.RNibDataService, ranStatusChangeManager managers.IRanStatusChangeManager, x2ResetResponseExtractor converters.IX2ResetResponseExtractor) X2ResetResponseHandler {
return X2ResetResponseHandler{
logger: logger,
rnibDataService: rnibDataService,
ranStatusChangeManager: ranStatusChangeManager,
extractor: x2ResetResponseExtractor,
}
}
func (h X2ResetResponseHandler) Handle(request *models.NotificationRequest) {
ranName := request.RanName
h.logger.Infof("#X2ResetResponseHandler.Handle - RAN name: %s - received reset response. Payload: %x", ranName, request.Payload)
nodebInfo, err := h.rnibDataService.GetNodeb(ranName)
if err != nil {
h.logger.Errorf("#x2ResetResponseHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
return
}
if nodebInfo.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
h.logger.Warnf("#X2ResetResponseHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", nodebInfo.RanName, nodebInfo.ConnectionStatus)
h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
return
}
if nodebInfo.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
h.logger.Errorf("#X2ResetResponseHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", nodebInfo.RanName, nodebInfo.ConnectionStatus)
h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
return
}
isSuccessfulResetResponse, err := h.isSuccessfulResetResponse(ranName, request.Payload)
h.logger.Infof("#X2ResetResponseHandler.Handle - Summary: elapsed time for receiving and handling reset request message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
if err != nil || !isSuccessfulResetResponse {
return
}
_ = h.ranStatusChangeManager.Execute(rmrCgo.RAN_RESTARTED, enums.RIC_TO_RAN, nodebInfo)
}
func (h X2ResetResponseHandler) isSuccessfulResetResponse(ranName string, packedBuffer []byte) (bool, error) {
criticalityDiagnostics, err := h.extractor.ExtractCriticalityDiagnosticsFromPdu(packedBuffer)
if err != nil {
h.logger.Errorf("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Failed extracting pdu: %s", ranName, err)
return false, err
}
if criticalityDiagnostics != nil {
h.logger.Errorf("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Unsuccessful RESET response message. Criticality diagnostics: %s", ranName, criticalityDiagnostics)
return false, nil
}
h.logger.Infof("#X2ResetResponseHandler.isSuccessfulResetResponse - RAN name: %s - Successful RESET response message", ranName)
return true, nil
}

View File

@@ -0,0 +1,185 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/configuration"
"e2mgr/converters"
"e2mgr/enums"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"testing"
"time"
)
const (
SuccessfulX2ResetResponsePackedPdu = "200700080000010011400100"
SuccessfulX2ResetResponsePackedPduEmptyIEs = "20070003000000"
UnsuccessfulX2ResetResponsePackedPdu = "2007000d00000100114006080000000d00"
)
func initX2ResetResponseHandlerTest(t *testing.T) (X2ResetResponseHandler, *mocks.RnibReaderMock, *mocks.RmrMessengerMock) {
log, err := logger.InitLogger(logger.InfoLevel)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
if err != nil {
t.Errorf("#initX2ResetResponseHandlerTest - failed to initialize logger, error: %s", err)
}
readerMock := &mocks.RnibReaderMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := initRmrSender(rmrMessengerMock, log)
ranStatusChangeManager := managers.NewRanStatusChangeManager(log, rmrSender)
h := NewX2ResetResponseHandler(log, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(log))
return h, readerMock, rmrMessengerMock
}
func TestX2ResetResponseSuccess(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
var payload []byte
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
if err != nil {
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
}
var xAction []byte
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
var rnibErr error
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RIC_TO_RAN)
rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
}
func TestX2ResetResponseSuccessEmptyIEs(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
var payload []byte
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPduEmptyIEs, "%x", &payload)
if err != nil {
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
}
var xAction []byte
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
var rnibErr error
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
ranRestartedMbuf := getRanRestartedMbuf(nb.NodeType, enums.RIC_TO_RAN)
rmrMessengerMock.On("SendMsg", ranRestartedMbuf, true).Return(&rmrCgo.MBuf{}, err)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertCalled(t, "SendMsg", ranRestartedMbuf, true)
}
func TestX2ResetResponseShuttingDown(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
var payload []byte
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
if err != nil {
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
}
var xAction []byte
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, NodeType: entities.Node_ENB}
var rnibErr error
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestX2ResetResponseInvalidConnectionStatus(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
var payload []byte
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
if err != nil {
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
}
var xAction []byte
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, NodeType: entities.Node_ENB}
var rnibErr error
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestX2ResetResponseError(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
var payload []byte
_, err := fmt.Sscanf(UnsuccessfulX2ResetResponsePackedPdu, "%x", &payload)
if err != nil {
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
}
var xAction []byte
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
var rnibErr error
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestX2ResetResponseGetNodebFailure(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
var payload []byte
_, err := fmt.Sscanf(SuccessfulX2ResetResponsePackedPdu, "%x", &payload)
if err != nil {
t.Fatalf("Failed converting packed pdu. Error: %v\n", err)
}
var xAction []byte
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
var nb *entities.NodebInfo
rnibErr := common.NewResourceNotFoundError("nodeb not found")
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}
func TestX2ResetResponseUnpackFailure(t *testing.T) {
h, readerMock, rmrMessengerMock := initX2ResetResponseHandlerTest(t)
payload := []byte("Invalid payload")
var xAction []byte
notificationRequest := models.NotificationRequest{RanName: RanName, Len: len(payload), Payload: payload, StartTime: time.Now(), TransactionId: xAction}
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, NodeType: entities.Node_ENB}
var rnibErr error
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
}

View File

@@ -0,0 +1,71 @@
//
// 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 rmrmsghandlers
// #cgo CFLAGS: -I../../3rdparty/asn1codec/inc/ -I../../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../../3rdparty/asn1codec/lib/ -L../../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <configuration_update_wrapper.h>
import "C"
import (
"e2mgr/converters"
"e2mgr/e2pdus"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services/rmrsender"
"e2mgr/utils"
)
type X2EnbConfigurationUpdateHandler struct {
logger *logger.Logger
rmrSender *rmrsender.RmrSender
}
func NewX2EnbConfigurationUpdateHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender) X2EnbConfigurationUpdateHandler {
return X2EnbConfigurationUpdateHandler{
logger: logger,
rmrSender: rmrSender,
}
}
func (h X2EnbConfigurationUpdateHandler) Handle(request *models.NotificationRequest) {
refinedMessage, err := converters.UnpackX2apPduAndRefine(h.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
if err != nil {
h.logger.Errorf("#x2enb_configuration_update_handler.Handle - unpack failed. Error: %v", err)
msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, request.RanName, e2pdus.PackedX2EnbConfigurationUpdateFailure, request.TransactionId, request.GetMsgSrc())
_ = h.rmrSender.Send(msg)
h.logger.Infof("#X2EnbConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling enb configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
return
}
h.logger.Infof("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message received")
h.logger.Debugf("#x2enb_configuration_update_handler.Handle - Enb configuration update initiating message payload: %s", refinedMessage.PduPrint)
msg := models.NewRmrMessage(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, request.RanName, e2pdus.PackedX2EnbConfigurationUpdateAck,request.TransactionId, request.GetMsgSrc())
_ = h.rmrSender.Send(msg)
h.logger.Infof("#X2EnbConfigurationUpdateHandler.Handle - Summary: elapsed time for receiving and handling enb configuration update initiating message from E2 terminator: %f ms", utils.ElapsedTime(request.StartTime))
}

View File

@@ -0,0 +1,77 @@
//
// 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 rmrmsghandlers
import (
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"fmt"
"testing"
"time"
"unsafe"
)
const PackedX2EnbConfigurationUpdateAck = "200800080000010011400100"
const PackedX2EnbConfigurationUpdateFailure = "400800080000010005400142"
func initX2EnbConfigurationUpdateHandlerTest(t *testing.T) (X2EnbConfigurationUpdateHandler, *mocks.RmrMessengerMock) {
log := initLog(t)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := initRmrSender(rmrMessengerMock, log)
h := NewX2EnbConfigurationUpdateHandler(log, rmrSender)
return h, rmrMessengerMock
}
func TestHandleX2EnbConfigUpdateSuccess(t *testing.T) {
h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
ranName := "test"
xAction := []byte("123456aa")
var payload []byte
_, _ = fmt.Sscanf(PackedX2EnbConfigurationUpdateAck, "%x", &payload)
var msgSrc unsafe.Pointer
mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_ACK, len(payload), ranName, &payload, &xAction, msgSrc)
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: mBuf.Len, Payload: *mBuf.Payload,
StartTime: time.Now(), TransactionId:xAction}
var err error
rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, err)
h.Handle(&notificationRequest)
rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
}
func TestHandleX2EnbConfigUpdateFailure(t *testing.T) {
h, rmrMessengerMock := initX2EnbConfigurationUpdateHandlerTest(t)
ranName := "test"
xAction := []byte("123456aa")
var payload []byte
_, _ = fmt.Sscanf(PackedX2EnbConfigurationUpdateFailure, "%x", &payload)
var msgSrc unsafe.Pointer
mBuf := rmrCgo.NewMBuf(rmrCgo.RIC_ENB_CONFIGURATION_UPDATE_FAILURE, len(payload), ranName, &payload, &xAction, msgSrc)
notificationRequest := models.NotificationRequest{RanName: mBuf.Meid, Len: 0, Payload: []byte{0},
StartTime: time.Now(), TransactionId:xAction}
rmrMessengerMock.On("SendMsg", mBuf, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("send failure"))
h.Handle(&notificationRequest)
rmrMessengerMock.AssertCalled(t, "SendMsg", mBuf, true)
}