372bf05a90566b18bec4172ef39d7a065aee6b7e
[ric-plt/e2mgr.git] / E2Manager / handlers / rmrmsghandlers / ric_service_update_handler_test.go
1 //
2 // Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
3 //
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
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15
16 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
17 //  platform project (RICP).
18
19 package rmrmsghandlers
20
21 import (
22         "bytes"
23         "e2mgr/configuration"
24         "e2mgr/mocks"
25         "e2mgr/models"
26         "e2mgr/rmrCgo"
27         "e2mgr/services"
28         "e2mgr/tests"
29         "e2mgr/utils"
30         "encoding/xml"
31         "fmt"
32         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
33         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
34         "github.com/stretchr/testify/assert"
35         "github.com/stretchr/testify/mock"
36         "testing"
37 )
38
39 const (
40         serviceUpdateE2tInstanceAddress = "10.0.0.27:9999"
41         serviceUpdateE2SetupMsgPrefix   = serviceUpdateE2tInstanceAddress + "|"
42         serviceUpdateRANName            = "gnb:TestRan"
43         RanManipulationMessageChannel   = "RAN_MANIPULATION"
44         RICServiceUpdate_E2SetupReqPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_SetupRequest.xml"
45         RicServiceUpdateModifiedPath    = "../../tests/resources/serviceUpdate/RicServiceUpdate_ModifiedFunction.xml"
46         RicServiceUpdateDeletePath      = "../../tests/resources/serviceUpdate/RicServiceUpdate_DeleteFunction.xml"
47         RicServiceUpdateAddedPath       = "../../tests/resources/serviceUpdate/RicServiceUpdate_AddedFunction.xml"
48         RicServiceUpdateEmptyPath               = "../../tests/resources/serviceUpdate/RicServiceUpdate_Empty.xml"
49         RicServiceUpdateAckModifiedPath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_ModifiedFunction.xml"
50         RicServiceUpdateAckAddedPath    = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_AddedFunction.xml"
51         RicServiceUpdateAckDeletePath   = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_DeleteFunction.xml"
52         RicServiceUpdateAckEmptyPath    = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_Empty.xml"
53 )
54
55 func initRicServiceUpdateHandler(t *testing.T) (*RicServiceUpdateHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.RanListManagerMock) {
56         logger := tests.InitLog(t)
57         config := &configuration.Configuration{
58                 RnibRetryIntervalMs:       10,
59                 MaxRnibConnectionAttempts: 3,
60                 RnibWriter: configuration.RnibWriterConfig{
61                         StateChangeMessageChannel: StateChangeMessageChannel,
62                         RanManipulationMessageChannel: RanManipulationMessageChannel,
63                 },
64                 GlobalRicId: struct {
65                         RicId string
66                         Mcc   string
67                         Mnc   string
68                 }{
69                         Mcc: "337",
70                         Mnc: "94",
71                         RicId: "AACCE",
72                 }}
73         rmrMessengerMock := &mocks.RmrMessengerMock{}
74         rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
75         readerMock := &mocks.RnibReaderMock{}
76         writerMock := &mocks.RnibWriterMock{}
77         rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
78         ranListManagerMock := &mocks.RanListManagerMock{}
79         handler := NewRicServiceUpdateHandler(logger, rmrSender, rnibDataService, ranListManagerMock)
80         return handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock
81 }
82
83
84 func TestRICServiceUpdateModifiedFuncSuccess(t *testing.T){
85         testServiceUpdateSuccess(t, RicServiceUpdateModifiedPath, RicServiceUpdateAckModifiedPath)
86 }
87
88 func TestRICServiceUpdateAddedFuncSuccess(t *testing.T){
89
90         testServiceUpdateSuccess(t, RicServiceUpdateAddedPath, RicServiceUpdateAckAddedPath)
91 }
92
93 func TestRICServiceUpdateDeleteFuncSuccess(t *testing.T){
94         testServiceUpdateSuccess(t, RicServiceUpdateDeletePath, RicServiceUpdateAckDeletePath)
95 }
96
97 func TestRICServiceUpdateEmptySuccess(t *testing.T){
98         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
99         xmlserviceUpdate  := utils.ReadXmlFile(t, RicServiceUpdateEmptyPath)
100         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
101         nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
102         oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
103         newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
104         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
105         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
106         ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t,RicServiceUpdateAckEmptyPath, notificationRequest )
107         ranListManagerMock.On("UpdateHealthcheckTimeStampReceived",nb1.RanName).Return(oldnbIdentity, newnbIdentity)
108         ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil)
109         rmrMessengerMock.On("SendMsg",ricServiceAckMsg,true).Return(&rmrCgo.MBuf{}, nil)
110
111         handler.Handle(notificationRequest)
112         writerMock.AssertExpectations(t)
113         rmrMessengerMock.AssertNumberOfCalls(t,"SendMsg", 1)
114         readerMock.AssertExpectations(t)
115         ranListManagerMock.AssertExpectations(t)
116 }
117
118 func TestRICServiceUpdateRnibFailure(t *testing.T){
119         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
120         xmlserviceUpdate  := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
121         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
122         readerMock.On("GetNodeb", serviceUpdateRANName).Return(&entities.NodebInfo{}, common.NewInternalError(fmt.Errorf("internal error")))
123         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
124
125         handler.Handle(notificationRequest)
126         writerMock.AssertExpectations(t)
127         rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
128         readerMock.AssertExpectations(t)
129         ranListManagerMock.AssertExpectations(t)
130 }
131
132 func TestRICServiceUpdateRnibNotFound(t *testing.T){
133         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
134         xmlserviceUpdate  := utils.ReadXmlFile(t, RicServiceUpdateModifiedPath)
135         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
136         readerMock.On("GetNodeb", serviceUpdateRANName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("nodeb not found"))
137         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
138
139         handler.Handle(notificationRequest)
140         writerMock.AssertExpectations(t)
141         rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
142         readerMock.AssertExpectations(t)
143         ranListManagerMock.AssertExpectations(t)
144 }
145
146 func TestRICServiceUpdateNodeBInfoFailure(t *testing.T){
147         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
148         xmlserviceUpdate  := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
149         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
150         nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
151         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
152         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
153         writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(common.NewInternalError(fmt.Errorf("internal error")))
154
155         handler.Handle(notificationRequest)
156         writerMock.AssertExpectations(t)
157         rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
158         readerMock.AssertExpectations(t)
159         ranListManagerMock.AssertExpectations(t)
160 }
161
162 func TestSendRICServiceUpdateAckFailure(t *testing.T){
163         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
164         xmlserviceUpdate  := utils.ReadXmlFile(t, RicServiceUpdateModifiedPath)
165         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
166         nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
167         oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
168         newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
169         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
170         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
171         ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t,RicServiceUpdateAckModifiedPath, notificationRequest )
172         ranListManagerMock.On("UpdateHealthcheckTimeStampReceived",nb1.RanName).Return(oldnbIdentity, newnbIdentity)
173         writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
174         rmrMessengerMock.On("SendMsg",ricServiceAckMsg,true).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr send failure"))
175         ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil)
176
177         handler.Handle(notificationRequest)
178         writerMock.AssertExpectations(t)
179         rmrMessengerMock.AssertNumberOfCalls(t,"SendMsg", 1)
180         readerMock.AssertExpectations(t)
181         ranListManagerMock.AssertExpectations(t)
182 }
183
184 func TestRICServiceUpdateUpdateNbIdentitiesFailure(t *testing.T){
185         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
186         xmlserviceUpdate  := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
187         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
188         nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
189         oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
190         newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
191         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
192         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
193         ranListManagerMock.On("UpdateHealthcheckTimeStampReceived",nb1.RanName).Return(oldnbIdentity, newnbIdentity)
194         ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(common.NewInternalError(fmt.Errorf("internal error")))
195         writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
196
197         handler.Handle(notificationRequest)
198         writerMock.AssertExpectations(t)
199         rmrMessengerMock.AssertNumberOfCalls(t,"SendMsg", 0)
200         readerMock.AssertExpectations(t)
201         ranListManagerMock.AssertExpectations(t)
202 }
203
204 func TestRICServiceUpdateParseRequest_PipFailure(t *testing.T) {
205         xmlGnb := utils.ReadXmlFile(t, RICServiceUpdate_E2SetupReqPath)
206         handler, _, _, _, _:= initRicServiceUpdateHandler(t)
207         prefBytes := []byte(serviceUpdateE2tInstanceAddress)
208         ricServiceUpdate, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...))
209         assert.Nil(t, ricServiceUpdate)
210         assert.NotNil(t, err)
211         assert.EqualError(t, err, "#RicServiceUpdateHandler.parseSetupRequest - Error parsing RIC SERVICE UPDATE failed extract Payload: no | separator found")
212 }
213
214 func TestRICServiceUppdateParseRequest_UnmarshalFailure(t *testing.T) {
215         handler, _, _, _, _ := initRicServiceUpdateHandler(t)
216         prefBytes := []byte(serviceUpdateE2SetupMsgPrefix)
217         ricServiceUpdate, err := handler.parseSetupRequest(append(prefBytes, 1, 2, 3))
218         assert.Nil(t, ricServiceUpdate)
219         assert.NotNil(t, err)
220         assert.EqualError(t, err, "#RicServiceUpdateHandler.parseSetupRequest - Error unmarshalling RIC SERVICE UPDATE payload: 31302e302e302e32373a393939397c010203")
221 }
222
223 func testServiceUpdateSuccess(t *testing.T, servicepdatePath string, serviceUpdateAckPath string){
224         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
225         xmlserviceUpdate  := utils.ReadXmlFile(t, servicepdatePath)
226         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
227         nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
228         oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
229         newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
230         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
231         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName,
232                 Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
233         ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t,serviceUpdateAckPath, notificationRequest )
234         ranListManagerMock.On("UpdateHealthcheckTimeStampReceived",nb1.RanName).Return(oldnbIdentity, newnbIdentity)
235         ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity},
236                 []*entities.NbIdentity{newnbIdentity}).Return(nil)
237         writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
238         rmrMessengerMock.On("SendMsg",ricServiceAckMsg,true).Return(&rmrCgo.MBuf{}, nil)
239
240         handler.Handle(notificationRequest)
241         writerMock.AssertExpectations(t)
242         rmrMessengerMock.AssertNumberOfCalls(t,"SendMsg", 1)
243         readerMock.AssertExpectations(t)
244         ranListManagerMock.AssertExpectations(t)
245 }
246
247 func createRicServiceQueryAckRMRMbuf(t *testing.T,  xmlFile string, req *models.NotificationRequest) *rmrCgo.MBuf{
248         ricServiceQueryAckXml := utils.ReadXmlFile(t, xmlFile)
249         ricServiceQueryAckXml = utils.CleanXML(ricServiceQueryAckXml)
250         payLoad := utils.NormalizeXml(ricServiceQueryAckXml)
251
252         xAction := req.TransactionId
253         msgsrc := req.GetMsgSrc()
254
255         rmrMessage := models.NewRmrMessage(rmrCgo.RIC_SERVICE_UPDATE_ACK, serviceUpdateRANName, payLoad, xAction, msgsrc)
256         return rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
257 }
258
259 func createNbInfo(t *testing.T, RanName string,  connectionStatus entities.ConnectionStatus) *entities.NodebInfo {
260         xmlgnb := utils.ReadXmlFile(t, RICServiceUpdate_E2SetupReqPath)
261         xmlgnb = utils.CleanXML(xmlgnb)
262         payload := append([]byte(serviceUpdateE2SetupMsgPrefix), xmlgnb...)
263         pipInd := bytes.IndexByte(payload, '|')
264         setupRequest := &models.E2SetupRequestMessage{}
265         err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
266         if err != nil {
267                 t.Fatal(err)
268         }
269
270         nodeb := &entities.NodebInfo{
271                 AssociatedE2TInstanceAddress: serviceUpdateE2tInstanceAddress,
272                 RanName:                      RanName,
273                 SetupFromNetwork:             true,
274                 NodeType:                     entities.Node_GNB,
275                 ConnectionStatus:                         connectionStatus,
276                 Configuration: &entities.NodebInfo_Gnb{
277                         Gnb: &entities.Gnb{
278                                 GnbType:      entities.GnbType_GNB,
279                                 RanFunctions: setupRequest.ExtractRanFunctionsList(),
280                         },
281                 },
282                 GlobalNbId: &entities.GlobalNbId{
283                         PlmnId: setupRequest.GetPlmnId(),
284                         NbId:   setupRequest.GetNbId(),
285                 },
286         }
287         return nodeb
288 }
289