Squash-merging e2ap-v2.0 branch
[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         "testing"
33
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"
38 )
39
40 const (
41         serviceUpdateE2tInstanceAddress = "10.0.0.27:9999"
42         serviceUpdateE2SetupMsgPrefix   = serviceUpdateE2tInstanceAddress + "|"
43         serviceUpdateRANName            = "gnb:TestRan"
44         RanManipulationMessageChannel   = "RAN_MANIPULATION"
45         RICServiceUpdate_E2SetupReqPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_SetupRequest.xml"
46         RicServiceUpdateModifiedPath    = "../../tests/resources/serviceUpdate/RicServiceUpdate_ModifiedFunction.xml"
47         RicServiceUpdateDeletePath      = "../../tests/resources/serviceUpdate/RicServiceUpdate_DeleteFunction.xml"
48         RicServiceUpdateAddedPath       = "../../tests/resources/serviceUpdate/RicServiceUpdate_AddedFunction.xml"
49         RicServiceUpdateEmptyPath       = "../../tests/resources/serviceUpdate/RicServiceUpdate_Empty.xml"
50         RicServiceUpdateAckModifiedPath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_ModifiedFunction.xml"
51         RicServiceUpdateAckAddedPath    = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_AddedFunction.xml"
52         RicServiceUpdateAckDeletePath   = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_DeleteFunction.xml"
53         RicServiceUpdateAckEmptyPath    = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_Empty.xml"
54 )
55
56 func initRicServiceUpdateHandler(t *testing.T) (*RicServiceUpdateHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.RanListManagerMock) {
57         logger := tests.InitLog(t)
58         config := &configuration.Configuration{
59                 RnibRetryIntervalMs:       10,
60                 MaxRnibConnectionAttempts: 3,
61                 RnibWriter: configuration.RnibWriterConfig{
62                         StateChangeMessageChannel:     StateChangeMessageChannel,
63                         RanManipulationMessageChannel: RanManipulationMessageChannel,
64                 },
65                 GlobalRicId: struct {
66                         RicId string
67                         Mcc   string
68                         Mnc   string
69                 }{
70                         Mcc:   "337",
71                         Mnc:   "94",
72                         RicId: "AACCE",
73                 }}
74         rmrMessengerMock := &mocks.RmrMessengerMock{}
75         rmrSender := tests.InitRmrSender(rmrMessengerMock, logger)
76         readerMock := &mocks.RnibReaderMock{}
77         writerMock := &mocks.RnibWriterMock{}
78         rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
79         ranListManagerMock := &mocks.RanListManagerMock{}
80         handler := NewRicServiceUpdateHandler(logger, rmrSender, rnibDataService, ranListManagerMock)
81         return handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock
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 TestRICServiceUpdateRnibFailure(t *testing.T) {
98         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
99         xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
100         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
101         readerMock.On("GetNodeb", serviceUpdateRANName).Return(&entities.NodebInfo{}, common.NewInternalError(fmt.Errorf("internal error")))
102         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
103
104         handler.Handle(notificationRequest)
105         writerMock.AssertExpectations(t)
106         rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
107         readerMock.AssertExpectations(t)
108         ranListManagerMock.AssertExpectations(t)
109 }
110
111 func TestRICServiceUpdateRnibNotFound(t *testing.T) {
112         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
113         xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateModifiedPath)
114         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
115         readerMock.On("GetNodeb", serviceUpdateRANName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("nodeb not found"))
116         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
117
118         handler.Handle(notificationRequest)
119         writerMock.AssertExpectations(t)
120         rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
121         readerMock.AssertExpectations(t)
122         ranListManagerMock.AssertExpectations(t)
123 }
124
125 func TestRICServiceUpdateNodeBInfoFailure(t *testing.T) {
126         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
127         xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
128         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
129         nb1 := createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
130         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
131         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
132         writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(common.NewInternalError(fmt.Errorf("internal error")))
133
134         handler.Handle(notificationRequest)
135         writerMock.AssertExpectations(t)
136         rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything)
137         readerMock.AssertExpectations(t)
138         ranListManagerMock.AssertExpectations(t)
139 }
140
141 func TestSendRICServiceUpdateAckFailure(t *testing.T) {
142         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
143         xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateModifiedPath)
144         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
145         nb1 := createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
146         oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
147         newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
148         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
149         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
150         ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t, RicServiceUpdateAckModifiedPath, notificationRequest)
151         ranListManagerMock.On("UpdateHealthcheckTimeStampReceived", nb1.RanName).Return(oldnbIdentity, newnbIdentity)
152         writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
153         rmrMessengerMock.On("SendMsg", ricServiceAckMsg, true).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr send failure"))
154         ranListManagerMock.On("UpdateNbIdentities", nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil)
155
156         handler.Handle(notificationRequest)
157         writerMock.AssertExpectations(t)
158         rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
159         readerMock.AssertExpectations(t)
160         ranListManagerMock.AssertExpectations(t)
161 }
162
163 func TestRICServiceUpdateUpdateNbIdentitiesFailure(t *testing.T) {
164         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
165         xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath)
166         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
167         nb1 := createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
168         oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
169         newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
170         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
171         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
172         ranListManagerMock.On("UpdateHealthcheckTimeStampReceived", nb1.RanName).Return(oldnbIdentity, newnbIdentity)
173         ranListManagerMock.On("UpdateNbIdentities", nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(common.NewInternalError(fmt.Errorf("internal error")))
174         writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
175
176         handler.Handle(notificationRequest)
177         writerMock.AssertExpectations(t)
178         rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 0)
179         readerMock.AssertExpectations(t)
180         ranListManagerMock.AssertExpectations(t)
181 }
182
183 func TestRICServiceUpdateParseRequest_PipFailure(t *testing.T) {
184         xmlGnb := utils.ReadXmlFile(t, RICServiceUpdate_E2SetupReqPath)
185         handler, _, _, _, _ := initRicServiceUpdateHandler(t)
186         prefBytes := []byte(serviceUpdateE2tInstanceAddress)
187         ricServiceUpdate, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...))
188         assert.Nil(t, ricServiceUpdate)
189         assert.NotNil(t, err)
190         assert.EqualError(t, err, "#RicServiceUpdateHandler.parseSetupRequest - Error parsing RIC SERVICE UPDATE failed extract Payload: no | separator found")
191 }
192
193 func TestRICServiceUppdateParseRequest_UnmarshalFailure(t *testing.T) {
194         handler, _, _, _, _ := initRicServiceUpdateHandler(t)
195         prefBytes := []byte(serviceUpdateE2SetupMsgPrefix)
196         ricServiceUpdate, err := handler.parseSetupRequest(append(prefBytes, 1, 2, 3))
197         assert.Nil(t, ricServiceUpdate)
198         assert.NotNil(t, err)
199         assert.EqualError(t, err, "#RicServiceUpdateHandler.parseSetupRequest - Error unmarshalling RIC SERVICE UPDATE payload: 31302e302e302e32373a393939397c010203")
200 }
201
202 func testServiceUpdateSuccess(t *testing.T, servicepdatePath string, serviceUpdateAckPath string) {
203         handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t)
204         xmlserviceUpdate := utils.ReadXmlFile(t, servicepdatePath)
205         xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate)
206         nb1 := createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED)
207         oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
208         newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus}
209         readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil)
210         notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName,
211                 Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)}
212         ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t, serviceUpdateAckPath, notificationRequest)
213         ranListManagerMock.On("UpdateHealthcheckTimeStampReceived", nb1.RanName).Return(oldnbIdentity, newnbIdentity)
214         ranListManagerMock.On("UpdateNbIdentities", nb1.NodeType, []*entities.NbIdentity{oldnbIdentity},
215                 []*entities.NbIdentity{newnbIdentity}).Return(nil)
216         writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil)
217         rmrMessengerMock.On("SendMsg", ricServiceAckMsg, true).Return(&rmrCgo.MBuf{}, nil)
218
219         handler.Handle(notificationRequest)
220         writerMock.AssertExpectations(t)
221         rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
222         readerMock.AssertExpectations(t)
223         ranListManagerMock.AssertExpectations(t)
224 }
225
226 func createRicServiceQueryAckRMRMbuf(t *testing.T, xmlFile string, req *models.NotificationRequest) *rmrCgo.MBuf {
227         ricServiceQueryAckXml := utils.ReadXmlFile(t, xmlFile)
228         ricServiceQueryAckXml = utils.CleanXML(ricServiceQueryAckXml)
229         payLoad := utils.NormalizeXml(ricServiceQueryAckXml)
230
231         xAction := req.TransactionId
232         msgsrc := req.GetMsgSrc()
233
234         rmrMessage := models.NewRmrMessage(rmrCgo.RIC_SERVICE_UPDATE_ACK, serviceUpdateRANName, payLoad, xAction, msgsrc)
235         return rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc())
236 }
237
238 func createNbInfo(t *testing.T, RanName string, connectionStatus entities.ConnectionStatus) *entities.NodebInfo {
239         xmlgnb := utils.ReadXmlFile(t, RICServiceUpdate_E2SetupReqPath)
240         xmlgnb = utils.CleanXML(xmlgnb)
241         payload := append([]byte(serviceUpdateE2SetupMsgPrefix), xmlgnb...)
242         pipInd := bytes.IndexByte(payload, '|')
243         setupRequest := &models.E2SetupRequestMessage{}
244         err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
245         if err != nil {
246                 t.Fatal(err)
247         }
248
249         nodeb := &entities.NodebInfo{
250                 AssociatedE2TInstanceAddress: serviceUpdateE2tInstanceAddress,
251                 RanName:                      RanName,
252                 SetupFromNetwork:             true,
253                 NodeType:                     entities.Node_GNB,
254                 ConnectionStatus:             connectionStatus,
255                 Configuration: &entities.NodebInfo_Gnb{
256                         Gnb: &entities.Gnb{
257                                 GnbType:      entities.GnbType_GNB,
258                                 RanFunctions: setupRequest.ExtractRanFunctionsList(),
259                         },
260                 },
261                 GlobalNbId: &entities.GlobalNbId{
262                         PlmnId: setupRequest.GetPlmnId(),
263                         NbId:   setupRequest.GetNbId(),
264                 },
265         }
266         return nodeb
267 }