1 // Copyright 2023 Nokia
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 // This source code is part of the near-RT RIC (RAN Intelligent Controller)
16 // platform project (RICP)
18 package rmrmsghandlers
34 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
35 "github.com/stretchr/testify/assert"
36 "github.com/stretchr/testify/mock"
40 RanNameForErrorIndication = "test"
41 E2tAddress = "10.10.2.15:9800"
42 e2tInstanceFullAddressErrorIndication = "10.0.2.15:9999"
43 e2SetupMsgPrefixErrorIndication = e2tInstanceFullAddressErrorIndication + "|"
44 ErrorIndicationXmlPath = "../../tests/resources/errorIndication/ErrorIndicationForSetupRequest.xml"
45 ErrorIndicationWithoutCDXmlPath = "../../tests/resources/errorIndication/ErrorIndicationWithoutCD.xml"
46 ErrorIndicationXmlPathServiceUpdate = "../../tests/resources/errorIndication/ErrorIndicationForServiceUpdate.xml"
47 ErrorIndicationXmlPathUnsuccessfuOutcome = "../../tests/resources/errorIndication/ErrorIndicationUnsuccessfulOutcome.xml"
48 ErrorIndicationXmlPathDefault = "../../tests/resources/errorIndication/ErrorIndicationForDefault.xml"
49 ErrorIndicationInvalidXmlPath = "../../tests/resources/errorIndication/ErrorIndicationInvalid.xml"
52 func initErrorIndication(t *testing.T) (*ErrorIndicationHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock, *mocks.RoutingManagerClientMock, managers.RanListManager,*mocks.RanDisconnectionManagerMock,*mocks.RicServiceUpdateManagerMock, *mocks.MockLogger, *mocks.HttpClientMock,*mocks.RanListManagerMock) {
53 logger := tests.InitLog(t)
54 config := &configuration.Configuration{
55 RnibRetryIntervalMs: 10,
56 MaxRnibConnectionAttempts: 3,
57 RnibWriter: configuration.RnibWriterConfig{
58 StateChangeMessageChannel: StateChangeMessageChannel,
64 }{Mcc: "327", Mnc: "94", RicId: "AACCE"}}
65 rmrMessengerMock := &mocks.RmrMessengerMock{}
66 readerMock := &mocks.RnibReaderMock{}
67 writerMock := &mocks.RnibWriterMock{}
68 RanDisconnectionManagerMock := &mocks.RanDisconnectionManagerMock{}
69 ricServiceUpdateManagerMock := &mocks.RicServiceUpdateManagerMock{}
70 MockLogger := &mocks.MockLogger{}
71 routingManagerClientMock := &mocks.RoutingManagerClientMock{}
72 rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
73 e2tInstancesManagerMock := &mocks.E2TInstancesManagerMock{}
74 httpClientMock := &mocks.HttpClientMock{}
75 ranListManagerMock := &mocks.RanListManagerMock{}
77 ranListManager := managers.NewRanListManager(logger, rnibDataService)
78 ranAlarmService := services.NewRanAlarmService(logger, config)
79 ranConnectStatusChangeManager := managers.NewRanConnectStatusChangeManager(logger, rnibDataService, ranListManager, ranAlarmService)
80 e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManagerMock, routingManagerClientMock, ranConnectStatusChangeManager)
81 ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager, ranConnectStatusChangeManager)
82 RicServiceUpdateManager := managers.NewRicServiceUpdateManager(logger, rnibDataService)
83 handler := ErrorIndicationNotificationHandler(logger, ranDisconnectionManager, RicServiceUpdateManager)
85 return handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, ranListManager, RanDisconnectionManagerMock, ricServiceUpdateManagerMock,MockLogger,httpClientMock,ranListManagerMock
88 func TestParseErrorIndicationMessage_Success(t *testing.T) {
89 ErrorgnbXml := utils.ReadXmlFile(t, ErrorIndicationXmlPath)
90 handler, _, _, _, _, _, _, _, _,_,_,_ := initErrorIndication(t)
91 prefBytes := []byte(e2SetupMsgPrefixErrorIndication)
92 errorIndicationMessage, err := handler.parseErrorIndication(append(prefBytes, ErrorgnbXml...))
93 assert.NotNil(t, errorIndicationMessage)
97 func TestParseErrorIndication_PipFailure(t *testing.T) {
98 ErrorgnbXml := utils.ReadXmlFile(t, ErrorIndicationXmlPath)
99 handler, _, _, _, _, _,_ ,_, _, _,_,_ := initErrorIndication(t)
100 prefBytes := []byte("10.0.2.15:9999")
101 request, err := handler.parseErrorIndication(append(prefBytes, ErrorgnbXml...))
102 assert.Nil(t, request)
103 assert.NotNil(t, err)
104 assert.EqualError(t, err, "#ErrorIndicationHandler.parseErrorIndication - Error parsing ERROR INDICATION failed extract Payload: no | separator found")
106 func TestParseErrorIndicationMessage_UnmarshalFailure(t *testing.T) {
107 handler, _,_, _, _, _, _, _, _, _,_,_ := initErrorIndication(t)
108 prefBytes := []byte(e2SetupMsgPrefixErrorIndication)
109 errorIndicationMessage, err := handler.parseErrorIndication(append(prefBytes, 1, 2, 3))
110 assert.Nil(t, errorIndicationMessage)
111 assert.NotNil(t, err)
112 assert.EqualError(t, err, "#ErrorIndicationHandler.parseErrorIndication - Error unmarshalling ERROR INDICATION payload: 31302e302e322e31353a393939397c010203")
115 func testErrorIndicationNotificationHandler(t *testing.T) {
116 handler, readerMock, writerMock, _, _, _, _, _, _,_ ,_,_:= initErrorIndication(t)
117 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
118 notificationRequest := models.NotificationRequest{RanName: RanNameForErrorIndication}
119 handler.Handle(¬ificationRequest)
120 readerMock.AssertExpectations(t)
121 writerMock.AssertExpectations(t)
124 func testErrorIndicationHandlerWhenConnectedRanSuccess(t *testing.T,xmlPath string) {
125 xml := utils.ReadXmlFile(t, xmlPath)
126 handler, readerMock, writerMock, _, e2tInstancesManagerMock,routingManagerClientMock, _, _, _, _,httpClientMock,_ := initErrorIndication(t)
127 origNodebInfo := &entities.NodebInfo{
128 RanName: RanNameForErrorIndication,
129 GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"},
130 ConnectionStatus: entities.ConnectionStatus_CONNECTED,
131 AssociatedE2TInstanceAddress: E2tAddress,
134 models.UpdateProcedureType(RanNameForErrorIndication,models.E2SetupProcedureCompleted)
136 readerMock.On("GetNodeb", RanNameForErrorIndication).Return(origNodebInfo, rnibErr)
137 updatedNodebInfo1 := *origNodebInfo
138 updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
139 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, RanNameForErrorIndication+"_DISCONNECTED").Return(rnibErr)
140 updatedNodebInfo2 := *origNodebInfo
141 updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
142 updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
143 writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr)
144 e2tInstance := &entities.E2TInstance{Address: E2tAddress, AssociatedRanList: []string{RanNameForErrorIndication}}
145 readerMock.On("GetE2TInstance", E2tAddress).Return(e2tInstance, nil).Maybe()
146 e2tInstanceToSave := *e2tInstance
147 e2tInstanceToSave.AssociatedRanList = []string{}
148 //writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
149 mockHttpClientForErrorIndication(httpClientMock, true) //After uncommenting testcase is failing
150 e2tInstancesManagerMock.On("RemoveRanFromInstance", RanNameForErrorIndication, E2tAddress).Return(nil)
151 routingManagerClientMock.On("DissociateRanE2TInstance", E2tAddress, RanNameForErrorIndication).Return(nil)
152 notificationRequest := &models.NotificationRequest{RanName: RanNameForErrorIndication, Payload: append([]byte(e2SetupMsgPrefixErrorIndication), xml...)}
155 handler.Handle(notificationRequest)
156 readerMock.AssertExpectations(t)
157 writerMock.AssertExpectations(t)
158 httpClientMock.AssertExpectations(t)
159 writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
161 func TestErrorIndicationHandlerWhenConnectedGnbSuccessE2Setup(t *testing.T) {
162 testErrorIndicationHandlerWhenConnectedRanSuccess(t, ErrorIndicationXmlPath)
165 func TestErrorIndicationHandlerWhenConnectedGnbSuccessProcedureType(t *testing.T) {
166 testErrorIndicationHandlerWhenConnectedRanSuccess(t, ErrorIndicationWithoutCDXmlPath)
168 func TestErrorIndicationHandlerWhenConnectedGnbSuccessServiceUpdate(t *testing.T) {
169 testErrorIndicationHandlerWhenConnectedRanSuccessServiceUpdate(t, ErrorIndicationXmlPathServiceUpdate)
171 func TestErrorIndicationHandlerWhenConnectedGnbSuccessServiceUpdateProcedureType(t *testing.T) {
172 testErrorIndicationHandlerWhenConnectedRanSuccessServiceUpdate(t, ErrorIndicationWithoutCDXmlPath)
174 func TestErrorIndicationHandlerWhenConnectedGnbSuccessUnsuccessfulOutcome(t *testing.T) {
175 testErrorIndicationHandlerWhenConnectedRanSuccess(t, ErrorIndicationXmlPathUnsuccessfuOutcome)
177 func TestErrorIndicationHandlerInvalidXML(t *testing.T) {
178 testErrorIndicationHandlerInvalidXML(t, ErrorIndicationInvalidXmlPath)
180 func TestErrorIndicationHandlerForUnknownProcedureType(t *testing.T) {
181 testErrorIndicationHandlerWhenConnectedRanSuccessUnknownProcedureType(t,ErrorIndicationWithoutCDXmlPath)
183 func TestErrorIndicationHandlerForUnhandlingProcedureType(t *testing.T) {
184 testErrorIndicationHandlerWhenConnectedRanSuccessUnhandlingProcedureType(t,ErrorIndicationWithoutCDXmlPath)
186 func TestErrorIndicationHandlerForDefaultProcedureCode(t *testing.T) {
187 testErrorIndicationHandlerForDefaultProcedureCode(t,ErrorIndicationXmlPathDefault)
189 func mockHttpClientForErrorIndication(httpClientMock *mocks.HttpClientMock, isSuccessful bool) {
190 data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2tAddress, RanNameForErrorIndication)}
191 marshaled, _ := json.Marshal(data)
192 body := bytes.NewBuffer(marshaled)
193 respBody := ioutil.NopCloser(bytes.NewBufferString(""))
194 var respStatusCode int
196 respStatusCode = http.StatusCreated
198 respStatusCode = http.StatusBadRequest
200 httpClientMock.On("Post", clients.DissociateRanE2TInstanceApiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil).Maybe()
203 func testErrorIndicationHandlerWhenConnectedRanSuccessServiceUpdate(t *testing.T,xmlPath string) {
204 xml := utils.ReadXmlFile(t, xmlPath)
205 handler, readerMock, writerMock, _, _,_, _, _, _, _,_,_ := initErrorIndication(t)
206 origNodebInfo := &entities.NodebInfo{
207 RanName: RanNameForErrorIndication,
208 GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"},
209 ConnectionStatus: entities.ConnectionStatus_CONNECTED,
210 AssociatedE2TInstanceAddress: E2tAddress,
212 logger := tests.InitLog(t)
213 config := &configuration.Configuration{
214 RnibRetryIntervalMs: 10,
215 MaxRnibConnectionAttempts: 3,
216 RnibWriter: configuration.RnibWriterConfig{
217 StateChangeMessageChannel: StateChangeMessageChannel,
219 GlobalRicId: struct {
223 }{Mcc: "327", Mnc: "94", RicId: "AACCE"}}
224 rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
225 RicServiceUpdateManager := managers.NewRicServiceUpdateManager(logger, rnibDataService)
226 models.UpdateProcedureType(RanNameForErrorIndication,models.RicServiceUpdateCompleted)
229 readerMock.On("GetNodeb", RanNameForErrorIndication).Return(origNodebInfo, rnibErr)
230 updatedNodebInfo1 := *origNodebInfo
231 updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_CONNECTED
232 updatedNodebInfo2 := *origNodebInfo
233 updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
234 updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
235 e2tInstance := &entities.E2TInstance{Address: E2tAddress, AssociatedRanList: []string{RanNameForErrorIndication}}
236 readerMock.On("GetE2TInstance", E2tAddress).Return(e2tInstance, nil).Maybe()
237 e2tInstanceToSave := *e2tInstance
238 e2tInstanceToSave.AssociatedRanList = []string{}
239 writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
240 err := RicServiceUpdateManager.RevertRanFunctions(ranName)
243 notificationRequest := &models.NotificationRequest{RanName: RanNameForErrorIndication, Payload: append([]byte(e2SetupMsgPrefixErrorIndication), xml...)}
244 handler.Handle(notificationRequest)
245 readerMock.AssertExpectations(t)
246 writerMock.AssertExpectations(t)
248 func testErrorIndicationHandlerWhenConnectedRanSuccessUnknownProcedureType(t *testing.T,xmlPath string) {
249 xml := utils.ReadXmlFile(t, xmlPath)
250 handler, readerMock, writerMock, _, _,_, _, _, _, _,httpClientMock,_ := initErrorIndication(t)
252 models.UpdateProcedureType(RanNameForErrorIndication,models.E2SetupProcedureNotInitiated)
253 notificationRequest := &models.NotificationRequest{RanName: RanNameForErrorIndication, Payload: append([]byte(e2SetupMsgPrefixErrorIndication), xml...)}
254 handler.Handle(notificationRequest)
255 readerMock.AssertExpectations(t)
256 writerMock.AssertExpectations(t)
257 httpClientMock.AssertExpectations(t)
260 func testErrorIndicationHandlerWhenConnectedRanSuccessUnhandlingProcedureType(t *testing.T,xmlPath string) {
261 xml := utils.ReadXmlFile(t, xmlPath)
262 handler, readerMock, writerMock, _, _,_, _, _, _, _,httpClientMock,_ := initErrorIndication(t)
264 models.UpdateProcedureType(RanNameForErrorIndication,models.E2SetupProcedureFailure)
265 notificationRequest := &models.NotificationRequest{RanName: RanNameForErrorIndication, Payload: append([]byte(e2SetupMsgPrefixErrorIndication), xml...)}
267 handler.Handle(notificationRequest)
268 readerMock.AssertExpectations(t)
269 writerMock.AssertExpectations(t)
270 httpClientMock.AssertExpectations(t)
273 func testErrorIndicationHandlerInvalidXML(t *testing.T,xmlPath string) {
274 xml := utils.ReadXmlFile(t, xmlPath)
275 handler, readerMock, writerMock, _, _,_, _, _, _, _,httpClientMock,_ := initErrorIndication(t)
277 notificationRequest := &models.NotificationRequest{RanName: RanNameForErrorIndication, Payload: append([]byte(e2SetupMsgPrefixErrorIndication), xml...)}
279 handler.Handle(notificationRequest)
280 readerMock.AssertExpectations(t)
281 writerMock.AssertExpectations(t)
282 httpClientMock.AssertExpectations(t)
284 func testErrorIndicationHandlerForDefaultProcedureCode(t *testing.T,xmlPath string) {
285 xml := utils.ReadXmlFile(t, xmlPath)
286 handler, readerMock, writerMock, _, _,_, _, _, _, _,httpClientMock,_ := initErrorIndication(t)
288 notificationRequest := &models.NotificationRequest{RanName: RanNameForErrorIndication, Payload: append([]byte(e2SetupMsgPrefixErrorIndication), xml...)}
290 handler.Handle(notificationRequest)
291 readerMock.AssertExpectations(t)
292 writerMock.AssertExpectations(t)
293 httpClientMock.AssertExpectations(t)