// // Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // 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/configuration" "e2mgr/e2managererrors" "e2mgr/mocks" "e2mgr/models" "e2mgr/rmrCgo" "e2mgr/services" "e2mgr/utils" "encoding/xml" "errors" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "strings" "testing" "unsafe" ) const ( e2tInstanceFullAddress = "10.0.2.15:9999" e2SetupMsgPrefix = e2tInstanceFullAddress + "|" GnbSetupRequestXmlPath = "../../tests/resources/setupRequest/setupRequest_gnb.xml" ) func setupHealthCheckHandlerTest(t *testing.T) (*HealthCheckRequestHandler, services.RNibDataService, *mocks.RnibReaderMock, *mocks.RanListManagerMock, *mocks.RmrMessengerMock) { logger := initLog(t) config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3} readerMock := &mocks.RnibReaderMock{} writerMock := &mocks.RnibWriterMock{} rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) rmrMessengerMock := &mocks.RmrMessengerMock{} ranListManagerMock := &mocks.RanListManagerMock{} rmrSender := getRmrSender(rmrMessengerMock, logger) handler := NewHealthCheckRequestHandler(logger, rnibDataService, ranListManagerMock, rmrSender) return handler, rnibDataService, readerMock, ranListManagerMock, rmrMessengerMock } func TestHealthCheckRequestHandlerArguementHasRanNameSuccess(t *testing.T) { handler, _, readerMock, ranListManagerMock, rmrMessengerMock := setupHealthCheckHandlerTest(t) ranNames := []string{"RanName_1"} nb1:= createNbIdentity(t,"RanName_1", entities.ConnectionStatus_CONNECTED) oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil) mbuf:= createRMRMbuf(t, nb1) rmrMessengerMock.On("SendMsg",mbuf,true).Return(mbuf,nil) ranListManagerMock.On("UpdateHealthcheckTimeStampSent",nb1.RanName).Return(oldnbIdentity, newnbIdentity) ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil) resp, err := handler.Handle(models.HealthCheckRequest{ranNames}) assert.IsType(t, &models.HealthCheckSuccessResponse{}, resp) assert.Nil(t, err) readerMock.AssertExpectations(t) } func TestHealthCheckRequestHandlerArguementHasNoRanNameSuccess(t *testing.T) { handler, _, readerMock, ranListManagerMock, rmrMessengerMock := setupHealthCheckHandlerTest(t) nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED}, {InventoryName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}} ranListManagerMock.On("GetNbIdentityList").Return(nbIdentityList) nb1:= createNbIdentity(t,"RanName_1", entities.ConnectionStatus_CONNECTED) oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil) mbuf:= createRMRMbuf(t, nb1) rmrMessengerMock.On("SendMsg",mbuf,true).Return(mbuf,nil) ranListManagerMock.On("UpdateHealthcheckTimeStampSent",nb1.RanName).Return(oldnbIdentity, newnbIdentity) ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil) nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED} readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) resp, err := handler.Handle(models.HealthCheckRequest{[]string{}}) assert.Nil(t, err) assert.IsType(t, &models.HealthCheckSuccessResponse{}, resp) } func TestHealthCheckRequestHandlerArguementHasNoRanConnectedFailure(t *testing.T) { handler, _, readerMock, ranListManagerMock, rmrMessengerMock := setupHealthCheckHandlerTest(t) nbIdentityList := []*entities.NbIdentity{{InventoryName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}, {InventoryName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}} ranListManagerMock.On("GetNbIdentityList").Return(nbIdentityList) nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED} readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil) nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_SHUT_DOWN} readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil) _, err := handler.Handle(models.HealthCheckRequest{[]string{}}) rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything) ranListManagerMock.AssertNotCalled(t,"UpdateHealthcheckTimeStampSent",mock.Anything) ranListManagerMock.AssertNotCalled(t,"UpdateNbIdentities",mock.Anything, mock.Anything, mock.Anything) assert.IsType(t, &e2managererrors.NoConnectedRanError{}, err) } func TestHealthCheckRequestHandlerArguementHasRanNameDBErrorFailure(t *testing.T) { handler, _, readerMock, ranListManagerMock, rmrMessengerMock := setupHealthCheckHandlerTest(t) ranNames := []string{"RanName_1"} readerMock.On("GetNodeb", "RanName_1").Return(&entities.NodebInfo{}, errors.New("error")) _, err := handler.Handle(models.HealthCheckRequest{ranNames}) rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything) ranListManagerMock.AssertNotCalled(t,"UpdateHealthcheckTimeStampSent",mock.Anything) ranListManagerMock.AssertNotCalled(t,"UpdateNbIdentities",mock.Anything, mock.Anything, mock.Anything) assert.IsType(t, &e2managererrors.RnibDbError{}, err) readerMock.AssertExpectations(t) } func createRMRMbuf(t *testing.T, nodebInfo *entities.NodebInfo) *rmrCgo.MBuf{ serviceQuery := models.NewRicServiceQueryMessage(nodebInfo.GetGnb().RanFunctions) payLoad, err := xml.Marshal(&serviceQuery.E2APPDU) payLoad = utils.NormalizeXml(payLoad) tagsToReplace := []string{"reject","ignore","protocolIEs"} payLoad = utils.ReplaceEmptyTagsWithSelfClosing(payLoad, tagsToReplace) if err != nil { t.Fatal(err) } var xAction []byte var msgSrc unsafe.Pointer rmrMessage := models.NewRmrMessage(rmrCgo.RIC_SERVICE_QUERY, nodebInfo.RanName, payLoad, xAction, msgSrc) return rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc()) } func createNbIdentity(t *testing.T, RanName string, connectionStatus entities.ConnectionStatus) *entities.NodebInfo { xmlgnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) payload := append([]byte(e2SetupMsgPrefix), xmlgnb...) pipInd := bytes.IndexByte(payload, '|') setupRequest := &models.E2SetupRequestMessage{} err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) if err != nil { t.Fatal(err) } nodeb := &entities.NodebInfo{ AssociatedE2TInstanceAddress: e2tInstanceFullAddress, RanName: RanName, SetupFromNetwork: true, NodeType: entities.Node_GNB, ConnectionStatus: connectionStatus, Configuration: &entities.NodebInfo_Gnb{ Gnb: &entities.Gnb{ GnbType: entities.GnbType_GNB, RanFunctions: setupRequest.ExtractRanFunctionsList(), }, }, GlobalNbId: &entities.GlobalNbId{ PlmnId: setupRequest.GetPlmnId(), NbId: setupRequest.GetNbId(), }, } return nodeb } func normalizeXml(payload []byte) []byte { xmlStr := string(payload) normalized := strings.NewReplacer("<", "<", ">", ">", "","","","", "","").Replace(xmlStr) return []byte(normalized) }