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,224 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import "C"
import (
"e2mgr/clients"
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"time"
)
type DeleteAllRequestHandler struct {
rnibDataService services.RNibDataService
rmrSender *rmrsender.RmrSender
config *configuration.Configuration
logger *logger.Logger
e2tInstancesManager managers.IE2TInstancesManager
rmClient clients.IRoutingManagerClient
}
const PartialSuccessDueToRmErrorMessage = "Operation succeeded except for routing manager outbound call"
func NewDeleteAllRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rnibDataService services.RNibDataService, e2tInstancesManager managers.IE2TInstancesManager, rmClient clients.IRoutingManagerClient) *DeleteAllRequestHandler {
return &DeleteAllRequestHandler{
logger: logger,
rnibDataService: rnibDataService,
rmrSender: rmrSender,
config: config,
e2tInstancesManager: e2tInstancesManager,
rmClient: rmClient,
}
}
func (h *DeleteAllRequestHandler) Handle(request models.Request) (models.IResponse, error) {
h.logger.Infof("#DeleteAllRequestHandler.Handle - handling shutdown request")
e2tAddresses, err := h.e2tInstancesManager.GetE2TAddresses()
if err != nil {
return nil, err
}
if len(e2tAddresses) == 0 {
err, _ = h.updateNodebs(h.updateNodebInfoForceShutdown)
return nil, err
}
dissocErr := h.rmClient.DissociateAllRans(e2tAddresses)
if dissocErr != nil {
h.logger.Warnf("#DeleteAllRequestHandler.Handle - routing manager failure. continue flow.")
}
err, updatedAtLeastOnce := h.updateNodebs(h.updateNodebInfoShuttingDown)
if err != nil {
return nil, err
}
err = h.e2tInstancesManager.ClearRansOfAllE2TInstances()
if err != nil {
return nil, err
}
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
err = h.rmrSender.Send(&rmrMessage)
if err != nil {
h.logger.Errorf("#DeleteAllRequestHandler.Handle - failed to send sctp clear all message to RMR: %s", err)
return nil, e2managererrors.NewRmrError()
}
if !updatedAtLeastOnce {
h.logger.Infof("#DeleteAllRequestHandler.Handle - DB wasn't updated, not activating timer")
if dissocErr != nil {
return models.NewRedButtonPartialSuccessResponseModel(PartialSuccessDueToRmErrorMessage), nil
}
return nil, nil
}
time.Sleep(time.Duration(h.config.BigRedButtonTimeoutSec) * time.Second)
h.logger.Infof("#DeleteAllRequestHandler.Handle - timer expired")
err, _ = h.updateNodebs(h.updateNodebInfoShutDown)
if err != nil {
return nil, err
}
if dissocErr != nil {
return models.NewRedButtonPartialSuccessResponseModel(PartialSuccessDueToRmErrorMessage), nil
}
return nil, nil
}
func (h *DeleteAllRequestHandler) updateNodebs(updateCb func(node *entities.NodebInfo) (error, bool)) (error, bool) {
nbIdentityList, err := h.rnibDataService.GetListNodebIds()
if err != nil {
h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodes list from rNib. Error: %s", err)
return e2managererrors.NewRnibDbError(), false
}
updatedAtLeastOnce := false
for _, nbIdentity := range nbIdentityList {
node, err := h.rnibDataService.GetNodeb(nbIdentity.InventoryName)
if err != nil {
_, ok := err.(*common.ResourceNotFoundError)
if !ok {
h.logger.Errorf("#DeleteAllRequestHandler.updateNodebs - failed to get nodeB entity for ran name: %s from rNib. error: %s", nbIdentity.InventoryName, err)
return e2managererrors.NewRnibDbError(), false
}
continue
}
err, updated := updateCb(node)
if err != nil {
return err, false
}
if updated {
updatedAtLeastOnce = true
}
}
return nil, updatedAtLeastOnce
}
func (h *DeleteAllRequestHandler) updateNodebInfoForceShutdown(node *entities.NodebInfo) (error, bool) {
err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, true)
if err != nil {
return err, false
}
return nil, true
}
func (h *DeleteAllRequestHandler) updateNodebInfoShuttingDown(node *entities.NodebInfo) (error, bool) {
if node.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN {
return nil, false
}
err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUTTING_DOWN, true)
if err != nil {
return err, false
}
return nil, true
}
func (h *DeleteAllRequestHandler) updateNodebInfoShutDown(node *entities.NodebInfo) (error, bool) {
if node.ConnectionStatus == entities.ConnectionStatus_SHUT_DOWN {
return nil, false
}
if node.ConnectionStatus != entities.ConnectionStatus_SHUTTING_DOWN {
h.logger.Warnf("#DeleteAllRequestHandler.updateNodebInfoShutDown - RAN name: %s - ignore, status is not Shutting Down", node.RanName)
return nil, false
}
err := h.updateNodebInfo(node, entities.ConnectionStatus_SHUT_DOWN, false)
if err != nil {
return err, false
}
return nil, true
}
func (h *DeleteAllRequestHandler) updateNodebInfo(node *entities.NodebInfo, connectionStatus entities.ConnectionStatus, resetAssociatedE2TAddress bool) error {
node.ConnectionStatus = connectionStatus
if resetAssociatedE2TAddress {
node.AssociatedE2TInstanceAddress = ""
}
err := h.rnibDataService.UpdateNodebInfo(node)
if err != nil {
h.logger.Errorf("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s - failed updating nodeB entity in rNib. error: %s", node.RanName, err)
return e2managererrors.NewRnibDbError()
}
h.logger.Infof("#DeleteAllRequestHandler.updateNodebInfo - RAN name: %s, connection status: %s", node.RanName, connectionStatus)
return nil
}

View File

@@ -0,0 +1,473 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"bytes"
"e2mgr/clients"
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"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"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"io/ioutil"
"net/http"
"testing"
)
func setupDeleteAllRequestHandlerTest(t *testing.T) (*DeleteAllRequestHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.HttpClientMock) {
log := initLog(t)
config := configuration.ParseConfiguration()
config.BigRedButtonTimeoutSec = 1
config.RoutingManager.BaseUrl = BaseRMUrl
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := getRmrSender(rmrMessengerMock, log)
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log)
httpClientMock := &mocks.HttpClientMock{}
rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
handler := NewDeleteAllRequestHandler(log, rmrSender, config, rnibDataService, e2tInstancesManager, rmClient)
return handler, readerMock, writerMock, rmrMessengerMock, httpClientMock
}
func mapE2TAddressesToE2DataList(e2tAddresses []string) models.RoutingManagerE2TDataList {
e2tDataList := make(models.RoutingManagerE2TDataList, len(e2tAddresses))
for i, v := range e2tAddresses {
e2tDataList[i] = models.NewRoutingManagerE2TData(v)
}
return e2tDataList
}
func mockHttpClientDissociateAllRans(httpClientMock *mocks.HttpClientMock, e2tAddresses []string, ok bool) {
data := mapE2TAddressesToE2DataList(e2tAddresses)
marshaled, _ := json.Marshal(data)
body := bytes.NewBuffer(marshaled)
url := BaseRMUrl + clients.DissociateRanE2TInstanceApiSuffix
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
var status int
if ok {
status = http.StatusOK
} else {
status = http.StatusBadRequest
}
httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: status, Body: respBody}, nil)
}
func TestGetE2TAddressesFailure(t *testing.T) {
h, readerMock, _, _, _ := setupDeleteAllRequestHandlerTest(t)
readerMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
}
func TestOneRanGetE2TAddressesEmptyList(t *testing.T) {
h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t)
readerMock.On("GetE2TAddresses").Return([]string{}, nil)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
_, err := h.Handle(nil)
assert.Nil(t, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestTwoRansGetE2TAddressesEmptyListOneGetNodebFailure(t *testing.T) {
h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t)
readerMock.On("GetE2TAddresses").Return([]string{}, nil)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
var nb2 *entities.NodebInfo
readerMock.On("GetNodeb", "RanName_2").Return(nb2, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t,&e2managererrors.RnibDbError{}, err)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
readerMock.AssertExpectations(t)
}
func TestTwoRansGetE2TAddressesEmptyListOneUpdateNodebInfoFailure(t *testing.T) {
h, readerMock, writerMock, _, _ := setupDeleteAllRequestHandlerTest(t)
readerMock.On("GetE2TAddresses").Return([]string{}, nil)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
updatedNb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb2).Return(common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t,&e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestOneRanDissociateSucceedsTryShuttingDownFailure(t *testing.T) {
h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
nbIdentityList := []*entities.NbIdentity{}
readerMock.On("GetListNodebIds").Return(nbIdentityList, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestOneRanDissociateFailsTryShuttingDownFailure(t *testing.T) {
h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, false)
nbIdentityList := []*entities.NbIdentity{}
readerMock.On("GetListNodebIds").Return(nbIdentityList, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestOneRanTryShuttingDownSucceedsClearFails(t *testing.T) {
h, readerMock, writerMock, _, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{}, common.NewInternalError(errors.New("error")))
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSendFails(t *testing.T) {
h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}}
readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil)
updatedE2tInstance := e2tInstance
updatedE2tInstance.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, e2managererrors.NewRmrError())
_, err := h.Handle(nil)
assert.IsType(t, &e2managererrors.RmrError{}, err)
rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t *testing.T, partial bool) {
h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, !partial)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}
nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN}
readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1", "RanName_2"}}
readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil)
updatedE2tInstance := e2tInstance
updatedE2tInstance.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
resp, err := h.Handle(nil)
assert.Nil(t, err)
if partial {
assert.IsType(t, &models.RedButtonPartialSuccessResponseModel{}, resp)
} else {
assert.Nil(t, resp)
}
rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
}
func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdownSuccess(t *testing.T) {
testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t, false)
}
func TestTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdownPartialSuccess(t *testing.T) {
testTwoRansTryShuttingDownSucceedsClearSucceedsRmrSucceedsAllRansAreShutdown(t, true)
}
//func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsAlreadyShutdown(t *testing.T) {
// h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
// e2tAddresses := []string{E2TAddress}
// readerMock.On("GetE2TAddresses").Return(e2tAddresses , nil)
// mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses ,true)
// nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
// nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
// readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
// updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
// writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
// readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
// e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}}
// readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance }, nil)
// updatedE2tInstance := e2tInstance
// updatedE2tInstance.AssociatedRanList = []string{}
// writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
//
// rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
// mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction)
// rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
//
// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
// nbAfterTimer := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
// readerMock.On("GetNodeb", /*"RanName_1"*/mock.Anything).Return(nbAfterTimer , nil) // Since this is a second call with same arguments we send mock.Anything due to mock limitations
// _, err := h.Handle(nil)
// assert.Nil(t, err)
// rmrMessengerMock.AssertCalled(t, "SendMsg",mbuf, true)
// readerMock.AssertExpectations(t)
// writerMock.AssertExpectations(t)
// writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
//}
//func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownUpdateFailure(t *testing.T) {
// h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
// e2tAddresses := []string{E2TAddress}
// readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
// mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
// nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
// //nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
// //readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
// updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
// writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
// readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
// e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}}
// readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil)
// updatedE2tInstance := e2tInstance
// updatedE2tInstance.AssociatedRanList = []string{}
// writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
//
// rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
// mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction)
// rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
//
// readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
// readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil)
// updatedNb2 := *updatedNb1
// updatedNb2.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
// writerMock.On("UpdateNodebInfo", &updatedNb2).Return(common.NewInternalError(errors.New("error")))
// _, err := h.Handle(nil)
// assert.IsType(t,&e2managererrors.RnibDbError{}, err)
// rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
// readerMock.AssertExpectations(t)
// writerMock.AssertExpectations(t)
//}
func testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t *testing.T, partial bool) {
h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, !partial)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
//nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
//readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1"}}
readerMock.On("GetE2TInstances", []string{E2TAddress}).Return([]*entities.E2TInstance{&e2tInstance}, nil)
updatedE2tInstance := e2tInstance
updatedE2tInstance.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil)
updatedNb2 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb2).Return(nil)
_, err := h.Handle(nil)
assert.Nil(t, err)
rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
}
func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownSuccess (t *testing.T) {
testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t, false)
}
func TestOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDownPartialSuccess (t *testing.T) {
testOneRanTryShuttingDownSucceedsClearSucceedsRmrSucceedsRanStatusIsShuttingDown(t, true)
}
func TestSuccessTwoE2TInstancesSixRans(t *testing.T) {
h, readerMock, writerMock, rmrMessengerMock, httpClientMock := setupDeleteAllRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress, E2TAddress2}
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
mockHttpClientDissociateAllRans(httpClientMock, e2tAddresses, true)
nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1"}, {InventoryName: "RanName_2"}, {InventoryName: "RanName_3"}, {InventoryName: "RanName_4"}, {InventoryName: "RanName_5"}, {InventoryName: "RanName_6"}}
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
//nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
//readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
//nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
//readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
//nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress}
//readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
//nb4 := &entities.NodebInfo{RanName: "RanName_4", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2}
//readerMock.On("GetNodeb", "RanName_4").Return(nb4, nil)
//nb5 := &entities.NodebInfo{RanName: "RanName_5", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2}
//readerMock.On("GetNodeb", "RanName_5").Return(nb5, nil)
//nb6 := &entities.NodebInfo{RanName: "RanName_6", ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: E2TAddress2}
//readerMock.On("GetNodeb", "RanName_6").Return(nb6, nil)
updatedNb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb1).Return(nil)
updatedNb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb2).Return(nil)
updatedNb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb3).Return(nil)
updatedNb4 := &entities.NodebInfo{RanName: "RanName_4", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb4).Return(nil)
updatedNb5 := &entities.NodebInfo{RanName: "RanName_5", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb5).Return(nil)
updatedNb6 := &entities.NodebInfo{RanName: "RanName_6", ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
writerMock.On("UpdateNodebInfo", updatedNb6).Return(nil)
readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"RanName_1", "RanName_2", "RanName_3"}}
e2tInstance2 := entities.E2TInstance{Address: E2TAddress2, AssociatedRanList: []string{"RanName_4", "RanName_5", "RanName_6"}}
readerMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{&e2tInstance, &e2tInstance2}, nil)
updatedE2tInstance := e2tInstance
updatedE2tInstance.AssociatedRanList = []string{}
updatedE2tInstance2 := e2tInstance2
updatedE2tInstance2.AssociatedRanList = []string{}
writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
writerMock.On("SaveE2TInstance", &updatedE2tInstance2).Return(nil)
rmrMessage := models.RmrMessage{MsgType: rmrCgo.RIC_SCTP_CLEAR_ALL}
mbuf := rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
rmrMessengerMock.On("SendMsg", mbuf, true).Return(mbuf, nil)
readerMock.On("GetListNodebIds").Return(nbIdentityList, nil)
readerMock.On("GetNodeb", "RanName_1").Return(updatedNb1, nil)
readerMock.On("GetNodeb", "RanName_2").Return(updatedNb2, nil)
readerMock.On("GetNodeb", "RanName_3").Return(updatedNb3, nil)
readerMock.On("GetNodeb", "RanName_4").Return(updatedNb4, nil)
readerMock.On("GetNodeb", "RanName_5").Return(updatedNb5, nil)
readerMock.On("GetNodeb", "RanName_6").Return(updatedNb6, nil)
updatedNb1AfterTimer := *updatedNb1
updatedNb1AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb1AfterTimer).Return(nil)
updatedNb2AfterTimer := *updatedNb2
updatedNb2AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb2AfterTimer).Return(nil)
updatedNb3AfterTimer := *updatedNb3
updatedNb3AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb3AfterTimer).Return(nil)
updatedNb4AfterTimer := *updatedNb4
updatedNb4AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb4AfterTimer).Return(nil)
updatedNb5AfterTimer := *updatedNb5
updatedNb5AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb5AfterTimer).Return(nil)
updatedNb6AfterTimer := *updatedNb6
updatedNb6AfterTimer.ConnectionStatus = entities.ConnectionStatus_SHUT_DOWN
writerMock.On("UpdateNodebInfo", &updatedNb6AfterTimer).Return(nil)
_, err := h.Handle(nil)
assert.Nil(t, err)
rmrMessengerMock.AssertCalled(t, "SendMsg", mbuf, true)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 12)
}
func initLog(t *testing.T) *logger.Logger {
log, err := logger.InitLogger(logger.DebugLevel)
if err != nil {
t.Errorf("#initLog test - failed to initialize logger, error: %s", err)
}
return log
}
func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
return rmrsender.NewRmrSender(log, rmrMessenger)
}

View File

@@ -0,0 +1,57 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
)
type GetE2TInstancesRequestHandler struct {
e2tInstancesManager managers.IE2TInstancesManager
logger *logger.Logger
}
func NewGetE2TInstancesRequestHandler(logger *logger.Logger, e2tInstancesManager managers.IE2TInstancesManager) *GetE2TInstancesRequestHandler {
return &GetE2TInstancesRequestHandler{
logger: logger,
e2tInstancesManager: e2tInstancesManager,
}
}
func (h *GetE2TInstancesRequestHandler) Handle(request models.Request) (models.IResponse, error) {
e2tInstances, err := h.e2tInstancesManager.GetE2TInstances()
if err != nil {
h.logger.Errorf("#GetE2TInstancesRequestHandler.Handle - Error fetching E2T instances from rNib: %s", err)
return nil, err
}
mapped := make([]*models.E2TInstanceResponseModel, len(e2tInstances))
for i, v := range e2tInstances {
mapped[i] = models.NewE2TInstanceResponseModel(v.Address, v.AssociatedRanList)
}
return models.E2TInstancesResponse(mapped), nil
}

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 httpmsghandlers
import (
"e2mgr/configuration"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"testing"
)
const E2TAddress2 = "10.0.2.15:3213"
func setupGetE2TInstancesListRequestHandlerTest(t *testing.T) (*GetE2TInstancesRequestHandler, *mocks.RnibReaderMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log)
handler := NewGetE2TInstancesRequestHandler(log, e2tInstancesManager)
return handler, readerMock
}
func TestGetE2TInstancesFailure(t *testing.T) {
handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, common.NewInternalError(errors.New("error")))
_, err := handler.Handle(nil)
assert.NotNil(t, err)
}
func TestGetE2TInstancesNoInstances(t *testing.T) {
handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
rnibReaderMock.On("GetE2TAddresses").Return([]string{}, nil)
resp, err := handler.Handle(nil)
assert.Nil(t, err)
assert.IsType(t, models.E2TInstancesResponse{}, resp)
assert.Len(t, resp, 0)
}
func TestGetE2TInstancesSuccess(t *testing.T) {
handler, rnibReaderMock := setupGetE2TInstancesListRequestHandlerTest(t)
e2tAddresses := []string{E2TAddress, E2TAddress2}
rnibReaderMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
e2tInstance := entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"test1", "test2"}}
e2tInstance2 := entities.E2TInstance{Address: E2TAddress2, AssociatedRanList: []string{"test3", "test4", "test5"}}
rnibReaderMock.On("GetE2TInstances", e2tAddresses).Return([]*entities.E2TInstance{&e2tInstance, &e2tInstance2}, nil)
resp, err := handler.Handle(nil)
assert.Nil(t, err)
assert.IsType(t, models.E2TInstancesResponse{}, resp)
assert.Len(t, resp, 2)
}

View File

@@ -0,0 +1,52 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/services"
)
type GetNodebIdListRequestHandler struct {
rNibDataService services.RNibDataService
logger *logger.Logger
}
func NewGetNodebIdListRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *GetNodebIdListRequestHandler {
return &GetNodebIdListRequestHandler{
logger: logger,
rNibDataService: rNibDataService,
}
}
func (handler *GetNodebIdListRequestHandler) Handle(request models.Request) (models.IResponse, error) {
nodebIdList, err := handler.rNibDataService.GetListNodebIds()
if err != nil {
handler.logger.Errorf("#GetNodebIdListRequestHandler.Handle - Error fetching Nodeb Identity list from rNib: %v", err)
return nil, e2managererrors.NewRnibDbError()
}
return models.NewGetNodebIdListResponse(nodebIdList), nil
}

View File

@@ -0,0 +1,62 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/configuration"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"testing"
)
func setupGetNodebIdListRequestHandlerTest(t *testing.T) (*GetNodebIdListRequestHandler, *mocks.RnibReaderMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
handler := NewGetNodebIdListRequestHandler(log, rnibDataService)
return handler, readerMock
}
func TestHandleGetNodebIdListSuccess(t *testing.T) {
handler, readerMock := setupGetNodebIdListRequestHandlerTest(t)
var rnibError error
readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{}, rnibError)
response, err := handler.Handle(nil)
assert.Nil(t, err)
assert.NotNil(t, response)
assert.IsType(t, &models.GetNodebIdListResponse{}, response)
}
func TestHandleGetNodebIdListFailure(t *testing.T) {
handler, readerMock := setupGetNodebIdListRequestHandlerTest(t)
var nodebIdList []*entities.NbIdentity
readerMock.On("GetListNodebIds").Return(nodebIdList, common.NewInternalError(errors.New("#reader.GetListNodebIds - Internal Error")))
response, err := handler.Handle(nil)
assert.NotNil(t, err)
assert.Nil(t, response)
}

View File

@@ -0,0 +1,62 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
)
type GetNodebRequestHandler struct {
rNibDataService services.RNibDataService
logger *logger.Logger
}
func NewGetNodebRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *GetNodebRequestHandler {
return &GetNodebRequestHandler{
logger: logger,
rNibDataService: rNibDataService,
}
}
func (handler *GetNodebRequestHandler) Handle(request models.Request) (models.IResponse, error) {
getNodebRequest := request.(models.GetNodebRequest)
ranName:= getNodebRequest.RanName
nodeb, err := handler.rNibDataService.GetNodeb(ranName)
if err != nil {
handler.logger.Errorf("#GetNodebRequestHandler.Handle - RAN name: %s - Error fetching RAN from rNib: %v", ranName, err)
return nil, rnibErrorToE2ManagerError(err)
}
return models.NewGetNodebResponse(nodeb), nil
}
func rnibErrorToE2ManagerError(err error) error {
_, ok := err.(*common.ResourceNotFoundError)
if ok {
return e2managererrors.NewResourceNotFoundError()
}
return e2managererrors.NewRnibDbError()
}

View File

@@ -0,0 +1,64 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/configuration"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"testing"
)
func setupGetNodebRequestHandlerTest(t *testing.T) (*GetNodebRequestHandler, *mocks.RnibReaderMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, nil)
handler := NewGetNodebRequestHandler(log, rnibDataService)
return handler, readerMock
}
func TestHandleGetNodebSuccess(t *testing.T) {
handler, readerMock := setupGetNodebRequestHandlerTest(t)
ranName := "test1"
var rnibError error
readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{RanName:ranName}, rnibError)
response, err := handler.Handle(models.GetNodebRequest{RanName: ranName})
assert.Nil(t, err)
assert.NotNil(t, response)
assert.IsType(t, &models.GetNodebResponse{}, response)
}
func TestHandleGetNodebFailure(t *testing.T) {
handler, readerMock := setupGetNodebRequestHandlerTest(t)
ranName := "test1"
var nodebInfo *entities.NodebInfo
readerMock.On("GetNodeb", ranName).Return(nodebInfo, common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")))
response, err := handler.Handle(models.GetNodebRequest{RanName: ranName})
assert.NotNil(t, err)
assert.Nil(t, response)
}

View File

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

View File

@@ -0,0 +1,221 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/managers"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/go-ozzo/ozzo-validation"
"github.com/go-ozzo/ozzo-validation/is"
)
const (
X2SetupActivityName = "X2_SETUP"
EndcSetupActivityName = "ENDC_SETUP"
)
type SetupRequestHandler struct {
rNibDataService services.RNibDataService
logger *logger.Logger
ranSetupManager managers.IRanSetupManager
protocol entities.E2ApplicationProtocol
e2tAssociationManager *managers.E2TAssociationManager
e2tInstancesManager managers.IE2TInstancesManager
}
func NewSetupRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService,
ranSetupManager managers.IRanSetupManager, protocol entities.E2ApplicationProtocol, e2tInstancesManager managers.IE2TInstancesManager, e2tAssociationManager *managers.E2TAssociationManager) *SetupRequestHandler {
return &SetupRequestHandler{
logger: logger,
rNibDataService: rNibDataService,
ranSetupManager: ranSetupManager,
protocol: protocol,
e2tAssociationManager: e2tAssociationManager,
e2tInstancesManager: e2tInstancesManager,
}
}
func (h *SetupRequestHandler) Handle(request models.Request) (models.IResponse, error) {
setupRequest := request.(models.SetupRequest)
err := h.validateRequestDetails(setupRequest)
if err != nil {
return nil, err
}
nodebInfo, err := h.rNibDataService.GetNodeb(setupRequest.RanName)
if err != nil {
_, ok := err.(*common.ResourceNotFoundError)
if !ok {
h.logger.Errorf("#SetupRequestHandler.Handle - failed to get nodeB entity for ran name: %v from RNIB. Error: %s", setupRequest.RanName, err)
return nil, e2managererrors.NewRnibDbError()
}
result := h.connectNewRan(&setupRequest, h.protocol)
return nil, result
}
if nodebInfo.ConnectionStatus == entities.ConnectionStatus_SHUTTING_DOWN {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN: %s in wrong state (%s)", nodebInfo.RanName, entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
result := e2managererrors.NewWrongStateError(h.getActivityName(h.protocol), entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
return nil, result
}
if len(nodebInfo.AssociatedE2TInstanceAddress) != 0 {
result := h.connectExistingRanWithAssociatedE2TAddress(nodebInfo)
return nil, result
}
result := h.connectExistingRanWithoutAssociatedE2TAddress(nodebInfo)
return nil, result
}
func createInitialNodeInfo(requestDetails *models.SetupRequest, protocol entities.E2ApplicationProtocol) (*entities.NodebInfo, *entities.NbIdentity) {
nodebInfo := &entities.NodebInfo{
Ip: requestDetails.RanIp,
Port: uint32(requestDetails.RanPort),
ConnectionStatus: entities.ConnectionStatus_CONNECTING,
E2ApplicationProtocol: protocol,
RanName: requestDetails.RanName,
}
nbIdentity := &entities.NbIdentity{
InventoryName: requestDetails.RanName,
}
return nodebInfo, nbIdentity
}
func (h *SetupRequestHandler) connectExistingRanWithoutAssociatedE2TAddress(nodebInfo *entities.NodebInfo) error {
e2tAddress, err := h.e2tInstancesManager.SelectE2TInstance()
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed selecting E2T instance", nodebInfo.RanName)
if nodebInfo.ConnectionStatus == entities.ConnectionStatus_DISCONNECTED{
return err
}
nodebInfo.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
updateError := h.rNibDataService.UpdateNodebInfo(nodebInfo)
if updateError != nil {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed updating nodeb. error: %s", nodebInfo.RanName, updateError)
}
return err
}
err = h.e2tAssociationManager.AssociateRan(e2tAddress, nodebInfo)
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - failed associating ran to e2t address %s. error: %s", nodebInfo.RanName, e2tAddress, err)
return err
}
h.logger.Infof("#SetupRequestHandler.connectExistingRanWithoutAssociatedE2TAddress - RAN name: %s - successfully updated nodeb in rNib", nodebInfo.RanName)
result := h.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING)
return result
}
func (h *SetupRequestHandler) connectExistingRanWithAssociatedE2TAddress(nodebInfo *entities.NodebInfo) error {
status := entities.ConnectionStatus_CONNECTING
if nodebInfo.ConnectionStatus == entities.ConnectionStatus_CONNECTED {
status = nodebInfo.ConnectionStatus
}
err := h.rNibDataService.UpdateNodebInfo(nodebInfo)
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN name: %s - failed resetting connection attempts of RAN. error: %s", nodebInfo.RanName, err)
return e2managererrors.NewRnibDbError()
}
h.logger.Infof("#SetupRequestHandler.connectExistingRanWithAssociatedE2TAddress - RAN name: %s - successfully reset connection attempts of RAN", nodebInfo.RanName)
result := h.ranSetupManager.ExecuteSetup(nodebInfo, status)
return result
}
func (h *SetupRequestHandler) connectNewRan(request *models.SetupRequest, protocol entities.E2ApplicationProtocol) error {
e2tAddress, err := h.e2tInstancesManager.SelectE2TInstance()
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed selecting E2T instance", request.RanName)
return err
}
nodebInfo, nodebIdentity := createInitialNodeInfo(request, protocol)
err = h.rNibDataService.SaveNodeb(nodebIdentity, nodebInfo)
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed to save initial nodeb entity in RNIB. error: %s", request.RanName, err)
return e2managererrors.NewRnibDbError()
}
h.logger.Infof("#SetupRequestHandler.connectNewRan - RAN name: %s - initial nodeb entity was saved to rNib", request.RanName)
err = h.e2tAssociationManager.AssociateRan(e2tAddress, nodebInfo)
if err != nil {
h.logger.Errorf("#SetupRequestHandler.connectNewRan - RAN name: %s - failed associating ran to e2t address %s. error: %s", request.RanName, e2tAddress, err)
return err
}
result := h.ranSetupManager.ExecuteSetup(nodebInfo, entities.ConnectionStatus_CONNECTING)
return result
}
func (handler *SetupRequestHandler) validateRequestDetails(request models.SetupRequest) error {
if request.RanPort == 0 {
handler.logger.Errorf("#SetupRequestHandler.validateRequestDetails - validation failure: port cannot be zero")
return e2managererrors.NewRequestValidationError()
}
err := validation.ValidateStruct(&request,
validation.Field(&request.RanIp, validation.Required, is.IP),
validation.Field(&request.RanName, validation.Required),
)
if err != nil {
handler.logger.Errorf("#SetupRequestHandler.validateRequestDetails - validation failure, error: %v", err)
return e2managererrors.NewRequestValidationError()
}
return nil
}
func (handler *SetupRequestHandler) getActivityName(protocol entities.E2ApplicationProtocol) string {
if protocol == entities.E2ApplicationProtocol_X2_SETUP_REQUEST {
return X2SetupActivityName
}
return EndcSetupActivityName
}

View File

@@ -0,0 +1,462 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"bytes"
"e2mgr/clients"
"e2mgr/configuration"
"e2mgr/e2managererrors"
"e2mgr/e2pdus"
"e2mgr/managers"
"e2mgr/mocks"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"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/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"io/ioutil"
"net/http"
"testing"
)
const E2TAddress = "10.0.2.15:8989"
const RanName = "test"
const BaseRMUrl = "http://10.10.2.15:12020/routingmanager"
func initSetupRequestTest(t *testing.T, protocol entities.E2ApplicationProtocol) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.E2TInstancesManagerMock, *mocks.RanSetupManagerMock, *mocks.HttpClientMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
config.RoutingManager.BaseUrl = BaseRMUrl
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
ranSetupManagerMock := &mocks.RanSetupManagerMock{}
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
httpClientMock := &mocks.HttpClientMock{}
mockHttpClientAssociateRan(httpClientMock)
rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
e2tAssociationManager := managers.NewE2TAssociationManager(log, rnibDataService, e2tInstancesManagerMock, rmClient)
handler := NewSetupRequestHandler(log, rnibDataService, ranSetupManagerMock, protocol, e2tInstancesManagerMock, e2tAssociationManager)
return readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, httpClientMock
}
func initSetupRequestTestBasicMocks(t *testing.T, protocol entities.E2ApplicationProtocol) (*mocks.RnibReaderMock, *mocks.RnibWriterMock, *SetupRequestHandler, *mocks.RmrMessengerMock, *mocks.HttpClientMock, *mocks.E2TInstancesManagerMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
config.RoutingManager.BaseUrl = BaseRMUrl
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := getRmrSender(rmrMessengerMock, log)
ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
httpClientMock := &mocks.HttpClientMock{}
rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
e2tAssociationManager := managers.NewE2TAssociationManager(log, rnibDataService, e2tInstancesManagerMock, rmClient)
handler := NewSetupRequestHandler(log, rnibDataService, ranSetupManager, protocol, e2tInstancesManagerMock, e2tAssociationManager)
return readerMock, writerMock, handler, rmrMessengerMock, httpClientMock, e2tInstancesManagerMock
}
func mockHttpClientAssociateRan(httpClientMock *mocks.HttpClientMock) {
data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)}
marshaled, _ := json.Marshal(data)
body := bytes.NewBuffer(marshaled)
url := BaseRMUrl + clients.AssociateRanToE2TInstanceApiSuffix
respBody := ioutil.NopCloser(bytes.NewBufferString(""))
httpClientMock.On("Post", url, "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
}
func TestX2SetupHandleNoPortError(t *testing.T) {
readerMock, _, handler, _, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
sr := models.SetupRequest{"127.0.0.1", 0, RanName,}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
readerMock.AssertNotCalled(t, "GetNodeb")
}
func TestX2SetupHandleNoRanNameError(t *testing.T) {
readerMock, _, handler, _, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
sr := models.SetupRequest{RanPort: 8080, RanIp: "127.0.0.1"}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
readerMock.AssertNotCalled(t, "GetNodeb")
}
func TestX2SetupHandleNoIpError(t *testing.T) {
readerMock, _, handler, _, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
sr := models.SetupRequest{RanPort: 8080, RanName: RanName}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
readerMock.AssertNotCalled(t, "GetNodeb")
}
func TestX2SetupHandleInvalidIpError(t *testing.T) {
readerMock, _, handler, _, _, _:= initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
sr := models.SetupRequest{RanPort: 8080, RanName: RanName, RanIp: "invalid ip"}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RequestValidationError{}, err)
readerMock.AssertNotCalled(t, "GetNodeb")
}
func TestSetupGetNodebFailure(t *testing.T) {
readerMock, _, handler, _, _, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
rnibErr := &common.ValidationError{}
nb := &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN,}
readerMock.On("GetNodeb", RanName).Return(nb, rnibErr)
sr := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(sr)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
}
func TestSetupNewRanSelectE2TInstancesDbError(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewRnibDbError())
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance")
writerMock.AssertNotCalled(t, "SaveNodeb")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupNewRanSelectE2TInstancesNoInstances(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, _ := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", mock.Anything, mock.Anything).Return(nil)
updatedNb := *nodebInfo
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(nil)
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.Nil(t, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
e2tInstancesManagerMock.AssertExpectations(t)
ranSetupManagerMock.AssertExpectations(t)
}
func TestSetupNewRanAssociateRanFailure(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, httpClientMock := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(e2managererrors.NewRnibDbError())
setupRequest := &models.SetupRequest{"127.0.0.1", 8080, RanName,}
nb, nbIdentity := createInitialNodeInfo(setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("SaveNodeb", nbIdentity, mock.Anything).Return(nil)
writerMock.On("UpdateNodebInfo", nb).Return(nil)
nb.AssociatedE2TInstanceAddress = E2TAddress
mockHttpClientAssociateRan(httpClientMock)
updatedNb := *nb
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
_, err := handler.Handle(*setupRequest)
assert.NotNil(t, err)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
e2tInstancesManagerMock.AssertExpectations(t)
ranSetupManagerMock.AssertExpectations(t)
httpClientMock.AssertExpectations(t)
}
func TestSetupNewRanSaveNodebFailure(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(common.NewInternalError(fmt.Errorf("")))
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupNewRanSetupDbError(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(e2managererrors.NewRnibDbError())
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
updatedNb := *nodebInfo
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
_, err := handler.Handle(setupRequest)
assert.NotNil(t, err)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
readerMock.AssertExpectations(t)
writerMock.AssertExpectations(t)
ranSetupManagerMock.AssertExpectations(t)
}
func TestSetupNewRanSetupRmrError(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
updatedNb := *nodebInfo
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRmrError())
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.RmrError{}, err)
}
func TestSetupNewRanSetupSuccess(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError(""))
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
nodebInfo, nbIdentity := createInitialNodeInfo(&setupRequest, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
writerMock.On("SaveNodeb", nbIdentity, nodebInfo).Return(nil)
updatedNb := *nodebInfo
updatedNb.AssociatedE2TInstanceAddress = E2TAddress
updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(nil)
_, err := handler.Handle(setupRequest)
assert.Nil(t, err)
}
func TestX2SetupExistingRanShuttingDown(t *testing.T) {
readerMock, _, handler, e2tInstancesManagerMock, ranSetupManagerMock , _:= initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}, nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.WrongStateError{}, err)
e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestEndcSetupExistingRanShuttingDown(t *testing.T) {
readerMock, _, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST)
readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN}, nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.WrongStateError{}, err)
e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupExistingRanWithoutAssocE2TInstanceSelectDbError(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewRnibDbError())
updatedNb := *nb
updatedNb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupExistingRanWithoutAssocE2TInstanceSelectNoInstanceError(t *testing.T) {
readerMock, writerMock, handler, rmrMessengerMock, httpClientMock,e2tInstancesManagerMock:= initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
readerMock.On("GetE2TAddresses").Return([]string{}, nil)
writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
e2tInstancesManagerMock.On("AddRansToInstance", "10.0.2.15:8989", []string{"test"}).Return(nil)
mockHttpClientAssociateRan(httpClientMock)
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.InternalError{}, err)
rmrMessengerMock.AssertNotCalled(t, "SendMsg")
writerMock.AssertExpectations(t)
}
func TestSetupExistingRanWithoutAssocE2TInstanceSelectNoInstanceErrorUpdateFailure(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
e2tInstancesManagerMock.On("SelectE2TInstance").Return("", e2managererrors.NewE2TInstanceAbsenceError())
updatedNb := *nb
updatedNb.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.E2TInstanceAbsenceError{}, err)
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupExistingRanWithoutAssocE2TInstanceSelectErrorAlreadyDisconnected(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, e2managererrors.NewE2TInstanceAbsenceError())
setupRequest := models.SetupRequest{"127.0.0.1", 8080, RanName,}
_, err := handler.Handle(setupRequest)
assert.IsType(t, &e2managererrors.E2TInstanceAbsenceError{}, err)
writerMock.AssertNotCalled(t, "UpdateNodebInfo")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
//func TestSetupExistingRanWithoutAssocE2TInstanceAssociateRanFailure(t *testing.T) {
// readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
// nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
// readerMock.On("GetNodeb", RanName).Return(nb, nil)
// e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
// e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(e2managererrors.NewRnibDbError())
// writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
// _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
// assert.IsType(t, &e2managererrors.RnibDbError{}, err)
// writerMock.AssertNotCalled(t, "UpdateNodebInfo")
// ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
//}
//func TestSetupExistingRanWithoutAssocE2TInstanceAssociateRanSucceedsUpdateNodebFails(t *testing.T) {
// readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
// nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
// readerMock.On("GetNodeb", RanName).Return(nb, nil)
// e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
// e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
// updatedNb := *nb
// updatedNb.AssociatedE2TInstanceAddress = E2TAddress
// writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
// _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
// assert.IsType(t, /* &e2managererrors.RnibDbError{} */&common.InternalError{}, err)
// ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
//}
//func TestSetupExistingRanWithoutAssocE2TInstanceExecuteSetupFailure(t *testing.T) {
// readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
// nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
// readerMock.On("GetNodeb", RanName).Return(nb, nil)
// e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
// e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
// updatedNb := *nb
// updatedNb.AssociatedE2TInstanceAddress = E2TAddress
// writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
// ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(e2managererrors.NewRnibDbError())
// _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
// assert.IsType(t, &e2managererrors.RnibDbError{}, err)
//}
//
//func TestSetupExistingRanWithoutAssocE2TInstanceSuccess(t *testing.T) {
// readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
// nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
// readerMock.On("GetNodeb", RanName).Return(nb, nil)
// e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
// e2tInstancesManagerMock.On("AddRansToInstance", E2TAddress, []string{RanName}).Return(nil)
// updatedNb := *nb
// updatedNb.AssociatedE2TInstanceAddress = E2TAddress
// writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
// ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTING).Return(nil)
// _, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
// assert.Nil(t, err)
//}
func TestSetupExistingRanWithAssocE2TInstanceUpdateNodebFailure(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
updatedNb := *nb
writerMock.On("UpdateNodebInfo", &updatedNb).Return(common.NewInternalError(fmt.Errorf("")))
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.IsType(t, &e2managererrors.RnibDbError{}, err)
e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance")
ranSetupManagerMock.AssertNotCalled(t, "ExecuteSetup")
}
func TestSetupExistingRanWithAssocE2TInstanceExecuteSetupRmrError(t *testing.T) {
readerMock, writerMock, handler, rmrMessengerMock, _, _ := initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
updatedNb := *nb
updatedNb3 := updatedNb
updatedNb3.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
payload := e2pdus.PackedX2setupRequest
xaction := []byte(RanName)
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), RanName, &payload, &xaction, nil)
rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg, e2managererrors.NewRmrError())
writerMock.On("UpdateNodebInfo", &updatedNb3).Return(nil)
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.IsType(t, &e2managererrors.RmrError{}, err)
writerMock.AssertExpectations(t)
}
func TestSetupExistingRanWithAssocE2TInstanceConnectedSuccess(t *testing.T) {
readerMock, writerMock, handler, e2tInstancesManagerMock, ranSetupManagerMock, _ := initSetupRequestTest(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
updatedNb := *nb
writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
ranSetupManagerMock.On("ExecuteSetup", &updatedNb, entities.ConnectionStatus_CONNECTED).Return(nil)
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.Nil(t, err)
e2tInstancesManagerMock.AssertNotCalled(t, "SelectE2TInstance")
e2tInstancesManagerMock.AssertNotCalled(t, "AddRansToInstance")
}
func TestSetupExistingRanWithoutAssocE2TInstanceExecuteRoutingManagerError(t *testing.T) {
readerMock, writerMock, handler, rmrMessengerMock, httpClientMock, e2tInstancesManagerMock := initSetupRequestTestBasicMocks(t, entities.E2ApplicationProtocol_X2_SETUP_REQUEST)
nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol:entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
readerMock.On("GetNodeb", RanName).Return(nb, nil)
writerMock.On("UpdateNodebInfo", nb).Return(nil)
e2tInstancesManagerMock.On("SelectE2TInstance").Return(E2TAddress, nil)
mockHttpClientAssociateRan(httpClientMock)
e2tInstancesManagerMock.On("AddRansToInstance", mock.Anything, mock.Anything).Return(nil)
msg := &rmrCgo.MBuf{}
var errNIl error
rmrMessengerMock.On("SendMsg",mock.Anything, true).Return(msg, errNIl)
_, err := handler.Handle(models.SetupRequest{"127.0.0.1", 8080, RanName,})
assert.Nil(t, err)
writerMock.AssertExpectations(t)
readerMock.AssertExpectations(t)
httpClientMock.AssertExpectations(t)
}

View File

@@ -0,0 +1,233 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/services"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
)
const VALIDATION_FAILURE_MESSAGE = "#UpdateGnbRequestHandler.Handle - validation failure: %s is a mandatory field"
type UpdateGnbRequestHandler struct {
logger *logger.Logger
rNibDataService services.RNibDataService
}
func NewUpdateGnbRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *UpdateGnbRequestHandler {
return &UpdateGnbRequestHandler{
logger: logger,
rNibDataService: rNibDataService,
}
}
func (h *UpdateGnbRequestHandler) Handle(request models.Request) (models.IResponse, error) {
updateGnbRequest := request.(models.UpdateGnbRequest)
h.logger.Infof("#UpdateGnbRequestHandler.Handle - Ran name: %s", updateGnbRequest.RanName)
err := h.validateRequestBody(updateGnbRequest)
if err != nil {
return nil, err
}
nodebInfo, err := h.rNibDataService.GetNodeb(updateGnbRequest.RanName)
if err != nil {
_, ok := err.(*common.ResourceNotFoundError)
if !ok {
h.logger.Errorf("#UpdateGnbRequestHandler.Handle - RAN name: %s - failed to get nodeb entity from RNIB. Error: %s", updateGnbRequest.RanName, err)
return nil, e2managererrors.NewRnibDbError()
}
h.logger.Errorf("#UpdateGnbRequestHandler.Handle - RAN name: %s - RAN not found on RNIB. Error: %s", updateGnbRequest.RanName, err)
return nil, e2managererrors.NewResourceNotFoundError()
}
err = h.updateGnbCells(nodebInfo, updateGnbRequest)
if err != nil {
return nil, err
}
return models.NewUpdateGnbResponse(nodebInfo), nil
}
func (h *UpdateGnbRequestHandler) updateGnbCells(nodebInfo *entities.NodebInfo, updateGnbRequest models.UpdateGnbRequest) error {
ranName := nodebInfo.RanName
gnb := nodebInfo.GetGnb()
if gnb == nil {
h.logger.Errorf("#UpdateGnbRequestHandler.updateGnbCells - RAN name: %s - nodeb missing gnb configuration", ranName)
return e2managererrors.NewInternalError()
}
if len(gnb.ServedNrCells) != 0 {
err := h.rNibDataService.RemoveServedNrCells(ranName, gnb.ServedNrCells)
if err != nil {
h.logger.Errorf("#UpdateGnbRequestHandler.updateGnbCells - RAN name: %s - Failed removing served nr cells", ranName)
return e2managererrors.NewRnibDbError()
}
}
gnb.ServedNrCells = updateGnbRequest.ServedNrCells
err := h.rNibDataService.UpdateGnbCells(nodebInfo, updateGnbRequest.ServedNrCells)
if err != nil {
h.logger.Errorf("#UpdateGnbRequestHandler.updateGnbCells - RAN name: %s - Failed updating GNB cells. Error: %s", ranName, err)
return e2managererrors.NewRnibDbError()
}
h.logger.Infof("#UpdateGnbRequestHandler.updateGnbCells - RAN name: %s - Successfully updated GNB cells", ranName)
return nil
}
func (h *UpdateGnbRequestHandler) validateRequestBody(updateGnbRequest models.UpdateGnbRequest) error {
if len(updateGnbRequest.ServedNrCells) == 0 {
h.logger.Errorf(VALIDATION_FAILURE_MESSAGE+" and cannot be empty", "servedCells")
return e2managererrors.NewRequestValidationError()
}
for _, servedNrCell := range updateGnbRequest.ServedNrCells {
if servedNrCell.ServedNrCellInformation == nil {
h.logger.Errorf(VALIDATION_FAILURE_MESSAGE+" and cannot be empty", "servedNrCellInformation")
return e2managererrors.NewRequestValidationError()
}
err := isServedNrCellInformationValid(servedNrCell.ServedNrCellInformation)
if err != nil {
h.logger.Errorf(VALIDATION_FAILURE_MESSAGE, err)
return e2managererrors.NewRequestValidationError()
}
if len(servedNrCell.NrNeighbourInfos) == 0 {
continue
}
for _, nrNeighbourInformation := range servedNrCell.NrNeighbourInfos {
err := isNrNeighbourInformationValid(nrNeighbourInformation)
if err != nil {
h.logger.Errorf(VALIDATION_FAILURE_MESSAGE, err)
return e2managererrors.NewRequestValidationError()
}
}
}
return nil
}
func isServedNrCellInformationValid(servedNrCellInformation *entities.ServedNRCellInformation) error {
if servedNrCellInformation.CellId == "" {
return errors.New("cellId")
}
if servedNrCellInformation.ChoiceNrMode == nil {
return errors.New("choiceNrMode")
}
if servedNrCellInformation.NrMode == entities.Nr_UNKNOWN {
return errors.New("nrMode")
}
if servedNrCellInformation.NrPci == 0 {
return errors.New("nrPci")
}
if len(servedNrCellInformation.ServedPlmns) == 0 {
return errors.New("servedPlmns")
}
return isServedNrCellInfoChoiceNrModeValid(servedNrCellInformation.ChoiceNrMode)
}
func isServedNrCellInfoChoiceNrModeValid(choiceNrMode *entities.ServedNRCellInformation_ChoiceNRMode) error {
if choiceNrMode.Fdd != nil {
return isServedNrCellInfoFddValid(choiceNrMode.Fdd)
}
if choiceNrMode.Tdd != nil {
return isServedNrCellInfoTddValid(choiceNrMode.Tdd)
}
return errors.New("served nr cell fdd / tdd")
}
func isServedNrCellInfoTddValid(tdd *entities.ServedNRCellInformation_ChoiceNRMode_TddInfo) error {
return nil
}
func isServedNrCellInfoFddValid(fdd *entities.ServedNRCellInformation_ChoiceNRMode_FddInfo) error {
return nil
}
func isNrNeighbourInformationValid(nrNeighbourInformation *entities.NrNeighbourInformation) error {
if nrNeighbourInformation.NrCgi == "" {
return errors.New("nrCgi")
}
if nrNeighbourInformation.ChoiceNrMode == nil {
return errors.New("choiceNrMode")
}
if nrNeighbourInformation.NrMode == entities.Nr_UNKNOWN {
return errors.New("nrMode")
}
if nrNeighbourInformation.NrPci == 0 {
return errors.New("nrPci")
}
return isNrNeighbourInfoChoiceNrModeValid(nrNeighbourInformation.ChoiceNrMode)
}
func isNrNeighbourInfoChoiceNrModeValid(choiceNrMode *entities.NrNeighbourInformation_ChoiceNRMode) error {
if choiceNrMode.Fdd != nil {
return isNrNeighbourInfoFddValid(choiceNrMode.Fdd)
}
if choiceNrMode.Tdd != nil {
return isNrNeighbourInfoTddValid(choiceNrMode.Tdd)
}
return errors.New("nr neighbour fdd / tdd")
}
func isNrNeighbourInfoTddValid(tdd *entities.NrNeighbourInformation_ChoiceNRMode_TddInfo) error {
return nil
}
func isNrNeighbourInfoFddValid(fdd *entities.NrNeighbourInformation_ChoiceNRMode_FddInfo) error {
return nil
}

View File

@@ -0,0 +1,99 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/e2managererrors"
"e2mgr/e2pdus"
"e2mgr/logger"
"e2mgr/models"
"e2mgr/rmrCgo"
"e2mgr/services"
"e2mgr/services/rmrsender"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"unsafe"
)
const (
X2_RESET_ACTIVITY_NAME = "X2_RESET"
)
type X2ResetRequestHandler struct {
rNibDataService services.RNibDataService
rmrSender *rmrsender.RmrSender
logger *logger.Logger
}
func NewX2ResetRequestHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService) *X2ResetRequestHandler {
return &X2ResetRequestHandler{
rNibDataService: rNibDataService,
rmrSender: rmrSender,
logger: logger,
}
}
func (handler *X2ResetRequestHandler) Handle(request models.Request) (models.IResponse, error) {
resetRequest := request.(models.ResetRequest)
handler.logger.Infof("#X2ResetRequestHandler.Handle - Ran name: %s", resetRequest.RanName)
if len(resetRequest.Cause) == 0 {
resetRequest.Cause = e2pdus.OmInterventionCause
}
payload, ok := e2pdus.KnownCausesToX2ResetPDU(resetRequest.Cause)
if !ok {
handler.logger.Errorf("#X2ResetRequestHandler.Handle - Unknown cause (%s)", resetRequest.Cause)
return nil, e2managererrors.NewRequestValidationError()
}
nodeb, err := handler.rNibDataService.GetNodeb(resetRequest.RanName)
if err != nil {
handler.logger.Errorf("#X2ResetRequestHandler.Handle - failed to get status of RAN: %s from RNIB. Error: %s", resetRequest.RanName, err.Error())
_, ok := err.(*common.ResourceNotFoundError)
if ok {
return nil, e2managererrors.NewResourceNotFoundError()
}
return nil, e2managererrors.NewRnibDbError()
}
if nodeb.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
handler.logger.Errorf("#X2ResetRequestHandler.Handle - RAN: %s in wrong state (%s)", resetRequest.RanName, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
return nil, e2managererrors.NewWrongStateError(X2_RESET_ACTIVITY_NAME, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)])
}
var xAction []byte
var msgSrc unsafe.Pointer
msg := models.NewRmrMessage(rmrCgo.RIC_X2_RESET, resetRequest.RanName, payload, xAction, msgSrc)
err = handler.rmrSender.Send(msg)
if err != nil {
handler.logger.Errorf("#X2ResetRequestHandler.Handle - failed to send reset message to RMR: %s", err)
return nil, e2managererrors.NewRmrError()
}
handler.logger.Infof("#X2ResetRequestHandler.Handle - sent x2 reset to RAN: %s with cause: %s", resetRequest.RanName, resetRequest.Cause)
return nil, nil
}

View File

@@ -0,0 +1,154 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package httpmsghandlers
import (
"e2mgr/configuration"
"e2mgr/e2managererrors"
"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"
"github.com/stretchr/testify/assert"
"testing"
"unsafe"
)
func setupX2ResetRequestHandlerTest(t *testing.T) (*X2ResetRequestHandler, *mocks.RmrMessengerMock, *mocks.RnibReaderMock) {
log := initLog(t)
config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
readerMock := &mocks.RnibReaderMock{}
writerMock := &mocks.RnibWriterMock{}
rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
rmrMessengerMock := &mocks.RmrMessengerMock{}
rmrSender := getRmrSender(rmrMessengerMock, log)
handler := NewX2ResetRequestHandler(log, rmrSender, rnibDataService)
return handler, rmrMessengerMock, readerMock
}
func TestHandleSuccessfulDefaultCause(t *testing.T) {
handler, rmrMessengerMock, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
// o&m intervention
payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
var xAction[]byte
var msgSrc unsafe.Pointer
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction, msgSrc)
rmrMessengerMock.On("SendMsg", msg, true).Return(msg, nil)
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.Nil(t, actual)
}
func TestHandleSuccessfulRequestedCause(t *testing.T) {
handler, rmrMessengerMock, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
var xAction[]byte
var msgSrc unsafe.Pointer
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction, msgSrc)
rmrMessengerMock.On("SendMsg", msg, true).Return(msg, nil)
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName, Cause: "protocol:transfer-syntax-error"})
assert.Nil(t, actual)
}
func TestHandleFailureUnknownCause(t *testing.T) {
handler, _, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName, Cause: "XXX"})
assert.IsType(t, e2managererrors.NewRequestValidationError(), actual)
}
func TestHandleFailureWrongState(t *testing.T) {
handler, _, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.IsType(t, e2managererrors.NewWrongStateError(X2_RESET_ACTIVITY_NAME, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)]), actual)
}
func TestHandleFailureRanNotFound(t *testing.T) {
handler, _, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("nodeb not found"))
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.IsType(t, e2managererrors.NewResourceNotFoundError(), actual)
}
func TestHandleFailureRnibError(t *testing.T) {
handler, _, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
readerMock.On("GetNodeb", ranName).Return(&entities.NodebInfo{}, common.NewInternalError(fmt.Errorf("internal error")))
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.IsType(t, e2managererrors.NewRnibDbError(), actual)
}
func TestHandleFailureRmrError(t *testing.T) {
handler, rmrMessengerMock, readerMock := setupX2ResetRequestHandlerTest(t)
ranName := "test1"
// o&m intervention
payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
var xAction[]byte
var msgSrc unsafe.Pointer
msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction, msgSrc)
rmrMessengerMock.On("SendMsg", msg, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr error"))
var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
_, actual := handler.Handle(models.ResetRequest{RanName: ranName})
assert.IsType(t, e2managererrors.NewRmrError(), actual)
}

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)
}