2 // Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
16 // This source code is part of the near-RT RIC (RAN Intelligent Controller)
17 // platform project (RICP).
19 package rmrmsghandlers
34 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
35 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
36 "github.com/stretchr/testify/assert"
37 "github.com/stretchr/testify/mock"
42 serviceUpdateE2tInstanceAddress = "10.0.0.27:9999"
43 serviceUpdateE2SetupMsgPrefix = serviceUpdateE2tInstanceAddress + "|"
44 serviceUpdateRANName = "gnb:TestRan"
45 RanManipulationMessageChannel = "RAN_MANIPULATION"
46 RICServiceUpdate_E2SetupReqPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_SetupRequest.xml"
47 RicServiceUpdateModifiedPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_ModifiedFunction.xml"
48 RicServiceUpdateDeletePath = "../../tests/resources/serviceUpdate/RicServiceUpdate_DeleteFunction.xml"
49 RicServiceUpdateAddedPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_AddedFunction.xml"
50 RicServiceUpdateEmptyPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_Empty.xml"
51 RicServiceUpdateAckModifiedPath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_ModifiedFunction.xml"
52 RicServiceUpdateAckAddedPath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_AddedFunction.xml"
53 RicServiceUpdateAckDeletePath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_DeleteFunction.xml"
54 RicServiceUpdateAckEmptyPath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_Empty.xml"
57 func initRicServiceUpdateHandler(t *testing.T) (*RicServiceUpdateHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.RanListManagerMock) {
58 logger := tests.InitLog(t)
59 config := &configuration.Configuration{
60 RnibRetryIntervalMs: 10,
61 MaxRnibConnectionAttempts: 3,
62 RnibWriter: configuration.RnibWriterConfig{
63 StateChangeMessageChannel: StateChangeMessageChannel,
64 RanManipulationMessageChannel: RanManipulationMessageChannel,
75 rmrMessengerMock := &mocks.RmrMessengerMock{}
76 rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
77 readerMock := &mocks.RnibReaderMock{}
78 writerMock := &mocks.RnibWriterMock{}
79 rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
80 ranListManagerMock := &mocks.RanListManagerMock{}
81 RicServiceUpdateManager := managers.NewRicServiceUpdateManager(logger, rnibDataService)
82 handler := NewRicServiceUpdateHandler(logger, rmrSender, rnibDataService, ranListManagerMock, RicServiceUpdateManager)
83 return handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock
86 func TestRICServiceUpdateModifiedFuncSuccess(t *testing.T) {
87 testServiceUpdateSuccess(t, RicServiceUpdateModifiedPath, RicServiceUpdateAckModifiedPath)
90 func TestRICServiceUpdateAddedFuncSuccess(t *testing.T) {
92 testServiceUpdateSuccess(t, RicServiceUpdateAddedPath, RicServiceUpdateAckAddedPath)
95 func TestRICServiceUpdateDeleteFuncSuccess(t *testing.T) {
96 testServiceUpdateSuccess(t, RicServiceUpdateDeletePath, RicServiceUpdateAckDeletePath)
99 func TestRICServiceUpdateRnibFailure(t *testing.T) {
100 handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
101 xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
102 xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
103 readerMock.On("GetNodeb", serviceUpdateRANName).Return(&entities.NodebInfo{}, common.NewInternalError(fmt.Errorf("internal error")))
104 notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
106 handler.Handle(notificationRequest)
107 writerMock.AssertExpectations(t)
108 rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
109 readerMock.AssertExpectations(t)
110 ranListManagerMock.AssertExpectations(t)
113 func TestRICServiceUpdateRnibNotFound(t *testing.T) {
114 handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
115 xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateModifiedPath)
116 xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
117 readerMock.On("GetNodeb", serviceUpdateRANName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("nodeb not found"))
118 notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
120 handler.Handle(notificationRequest)
121 writerMock.AssertExpectations(t)
122 rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
123 readerMock.AssertExpectations(t)
124 ranListManagerMock.AssertExpectations(t)
127 func TestRICServiceUpdateNodeBInfoFailure(t *testing.T) {
128 handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
129 xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
130 xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
131 nb1 := createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
132 readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
133 notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
134 writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(common.NewInternalError(fmt.Errorf("internal error")))
136 handler.Handle(notificationRequest)
137 writerMock.AssertExpectations(t)
138 rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
139 readerMock.AssertExpectations(t)
140 ranListManagerMock.AssertExpectations(t)
143 func TestSendRICServiceUpdateAckFailure(t *testing.T) {
144 handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
145 xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateModifiedPath)
146 xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
147 nb1 := createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
148 oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
149 newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
150 readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
151 notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
152 ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t, RicServiceUpdateAckModifiedPath, notificationRequest)
153 ranListManagerMock.On("UpdateHealthcheckTimeStampReceived", nb1.RanName).Return(oldnbIdentity, newnbIdentity)
154 writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
155 rmrMessengerMock.On("SendMsg", ricServiceAckMsg, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr send failure"))
156 ranListManagerMock.On("UpdateNbIdentities", nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil)
158 handler.Handle(notificationRequest)
159 writerMock.AssertExpectations(t)
160 rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
161 readerMock.AssertExpectations(t)
162 ranListManagerMock.AssertExpectations(t)
165 func TestRICServiceUpdateUpdateNbIdentitiesFailure(t *testing.T) {
166 handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
167 xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
168 xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
169 nb1 := createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
170 oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
171 newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
172 readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
173 notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
174 ranListManagerMock.On("UpdateHealthcheckTimeStampReceived", nb1.RanName).Return(oldnbIdentity, newnbIdentity)
175 ranListManagerMock.On("UpdateNbIdentities", nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(common.NewInternalError(fmt.Errorf("internal error")))
176 writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
178 handler.Handle(notificationRequest)
179 writerMock.AssertExpectations(t)
180 rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
181 readerMock.AssertExpectations(t)
182 ranListManagerMock.AssertExpectations(t)
185 func TestRICServiceUpdateParseRequest_PipFailure(t *testing.T) {
186 xmlGnb := utils.ReadXmlFile(t, RICServiceUpdate_E2SetupReqPath)
187 handler, _, _, _, _ := initRicServiceUpdateHandler(t)
188 prefBytes := []byte(serviceUpdateE2tInstanceAddress)
189 ricServiceUpdate, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...))
190 assert.Nil(t, ricServiceUpdate)
191 assert.NotNil(t, err)
192 assert.EqualError(t, err, "#RicServiceUpdateHandler.parseSetupRequest - Error parsing RIC SERVICE UPDATE failed extract Payload: no | separator found")
195 func TestRICServiceUppdateParseRequest_UnmarshalFailure(t *testing.T) {
196 handler, _, _, _, _ := initRicServiceUpdateHandler(t)
197 prefBytes := []byte(serviceUpdateE2SetupMsgPrefix)
198 ricServiceUpdate, err := handler.parseSetupRequest(append(prefBytes, 1, 2, 3))
199 assert.Nil(t, ricServiceUpdate)
200 assert.NotNil(t, err)
201 assert.EqualError(t, err, "#RicServiceUpdateHandler.parseSetupRequest - Error unmarshalling RIC SERVICE UPDATE payload: 31302e302e302e32373a393939397c010203")
204 func testServiceUpdateSuccess(t *testing.T, servicepdatePath string, serviceUpdateAckPath string) {
205 handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
206 xmlserviceUpdate := utils.ReadXmlFile(t, servicepdatePath)
207 xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
208 nb1 := createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
209 oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
210 newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
211 readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
212 notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName,
213 Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
214 ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t, serviceUpdateAckPath, notificationRequest)
215 ranListManagerMock.On("UpdateHealthcheckTimeStampReceived", nb1.RanName).Return(oldnbIdentity, newnbIdentity)
216 ranListManagerMock.On("UpdateNbIdentities", nb1.NodeType, []*entities.NbIdentity{oldnbIdentity},
217 []*entities.NbIdentity{newnbIdentity}).Return(nil)
218 writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
219 rmrMessengerMock.On("SendMsg", ricServiceAckMsg, true).Return(&rmrCgo.MBuf{}, nil)
221 handler.Handle(notificationRequest)
222 writerMock.AssertExpectations(t)
223 rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
224 readerMock.AssertExpectations(t)
225 ranListManagerMock.AssertExpectations(t)
228 func createRicServiceQueryAckRMRMbuf(t *testing.T, xmlFile string, req *models.NotificationRequest) *rmrCgo.MBuf {
229 ricServiceQueryAckXml := utils.ReadXmlFile(t, xmlFile)
230 ricServiceQueryAckXml = utils.CleanXML(ricServiceQueryAckXml)
231 payLoad := utils.NormalizeXml(ricServiceQueryAckXml)
233 xAction := req.TransactionId
234 msgsrc := req.GetMsgSrc()
236 rmrMessage := models.NewRmrMessage(rmrCgo.RIC_SERVICE_UPDATE_ACK, serviceUpdateRANName, payLoad, xAction, msgsrc)
237 return rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
240 func createNbInfo(t *testing.T, RanName string, connectionStatus entities.ConnectionStatus) *entities.NodebInfo {
241 xmlgnb := utils.ReadXmlFile(t, RICServiceUpdate_E2SetupReqPath)
242 xmlgnb = utils.CleanXML(xmlgnb)
243 payload := append([]byte(serviceUpdateE2SetupMsgPrefix), xmlgnb...)
244 pipInd := bytes.IndexByte(payload, '|')
245 setupRequest := &models.E2SetupRequestMessage{}
246 err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
251 nodeb := &entities.NodebInfo{
252 AssociatedE2TInstanceAddress: serviceUpdateE2tInstanceAddress,
254 SetupFromNetwork: true,
255 NodeType: entities.Node_GNB,
256 ConnectionStatus: connectionStatus,
257 Configuration: &entities.NodebInfo_Gnb{
259 GnbType: entities.GnbType_GNB,
260 RanFunctions: setupRequest.ExtractRanFunctionsList(),
263 GlobalNbId: &entities.GlobalNbId{
264 PlmnId: setupRequest.GetPlmnId(),
265 NbId: setupRequest.GetNbId(),