2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 // This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 // platform project (RICP).
26 "e2mgr/e2managererrors"
36 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
37 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
38 "github.com/pkg/errors"
39 "github.com/stretchr/testify/assert"
40 "github.com/stretchr/testify/mock"
45 StateChangeMessageChannel = "RAN_CONNECTION_STATUS_CHANGE"
48 func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
50 config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, RnibWriter: configuration.RnibWriterConfig{StateChangeMessageChannel: StateChangeMessageChannel}}
52 readerMock := &mocks.RnibReaderMock{}
53 writerMock := &mocks.RnibWriterMock{}
54 rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
56 e2tInstancesManager := NewE2TInstancesManager(rnibDataService, log)
57 httpClientMock := &mocks.HttpClientMock{}
58 rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
59 ranListManager := NewRanListManager(log, rnibDataService)
60 ranAlarmService := services.NewRanAlarmService(log, config)
61 ranConnectStatusChangeManager := NewRanConnectStatusChangeManager(log, rnibDataService, ranListManager, ranAlarmService)
62 e2tAssociationManager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager)
63 return e2tAssociationManager, readerMock, writerMock, httpClientMock
66 func mockHttpClient(httpClientMock *mocks.HttpClientMock, apiSuffix string, isSuccessful bool) {
67 data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)}
68 marshaled, _ := json.Marshal(data)
69 body := bytes.NewBuffer(marshaled)
70 respBody := ioutil.NopCloser(bytes.NewBufferString(""))
71 var respStatusCode int
73 respStatusCode = http.StatusCreated
75 respStatusCode = http.StatusBadRequest
77 httpClientMock.On("Post", apiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
80 func TestAssociateRanSuccess(t *testing.T) {
81 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
82 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
83 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
85 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
86 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, RanName+"_CONNECTED").Return(nil)
88 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
89 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
90 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
91 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
92 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
93 updatedE2tInstance := *e2tInstance
94 updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
95 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
97 _, err := manager.AssociateRan(E2TAddress, nb)
100 readerMock.AssertExpectations(t)
101 writerMock.AssertExpectations(t)
102 httpClientMock.AssertExpectations(t)
105 func TestAssociateRan_RnibError(t *testing.T) {
106 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
107 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
108 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
110 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
111 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, RanName+"_CONNECTED").Return(common.NewInternalError(fmt.Errorf("for tests")))
113 _, err := manager.AssociateRan(E2TAddress, nb)
115 assert.NotNil(t, err)
116 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
117 readerMock.AssertExpectations(t)
118 writerMock.AssertExpectations(t)
119 httpClientMock.AssertExpectations(t)
122 func TestAssociateRanRoutingManagerError(t *testing.T) {
123 manager, _, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
124 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, false)
125 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
126 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
128 _, err := manager.AssociateRan(E2TAddress, nb)
130 assert.NotNil(t, err)
131 assert.IsType(t, &e2managererrors.RoutingManagerError{}, err)
132 writerMock.AssertExpectations(t)
133 httpClientMock.AssertExpectations(t)
136 func TestAssociateRanUpdateNodebError(t *testing.T) {
137 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
138 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
139 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
142 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
143 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, RanName+"_CONNECTED").Return(nil)
145 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
146 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
147 writerMock.On("UpdateNodebInfo", mock.Anything).Return(e2managererrors.NewRnibDbError())
149 _, err := manager.AssociateRan(E2TAddress, nb)
151 assert.NotNil(t, err)
152 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
153 readerMock.AssertExpectations(t)
154 writerMock.AssertExpectations(t)
155 httpClientMock.AssertExpectations(t)
158 func TestAssociateRanGetE2tInstanceError(t *testing.T) {
159 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
160 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
161 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
164 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
165 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, RanName+"_CONNECTED").Return(nil)
168 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
169 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
170 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
171 var e2tInstance *entities.E2TInstance
172 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
174 _, err := manager.AssociateRan(E2TAddress, nb)
176 assert.NotNil(t, err)
177 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
178 readerMock.AssertExpectations(t)
179 writerMock.AssertExpectations(t)
180 httpClientMock.AssertExpectations(t)
183 func TestAssociateRanSaveE2tInstanceError(t *testing.T) {
184 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
185 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
186 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
189 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
190 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, ranName+"_CONNECTED").Return(nil)
193 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
194 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
195 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
196 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
197 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
198 updatedE2tInstance := *e2tInstance
199 updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
200 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
202 _, err := manager.AssociateRan(E2TAddress, nb)
204 assert.NotNil(t, err)
205 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
206 readerMock.AssertExpectations(t)
207 writerMock.AssertExpectations(t)
208 httpClientMock.AssertExpectations(t)
211 func TestDissociateRanSuccess(t *testing.T) {
212 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
213 mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, true)
214 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
215 readerMock.On("GetNodeb", RanName).Return(nb, nil)
217 updatedNb.AssociatedE2TInstanceAddress = ""
218 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
219 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
220 e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
221 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
222 updatedE2tInstance := *e2tInstance
223 updatedE2tInstance.AssociatedRanList = []string{}
224 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
226 err := manager.DissociateRan(E2TAddress, RanName)
229 readerMock.AssertExpectations(t)
230 writerMock.AssertExpectations(t)
231 httpClientMock.AssertExpectations(t)
234 func TestDissociateRanGetNodebError(t *testing.T) {
235 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
236 var nb *entities.NodebInfo
237 readerMock.On("GetNodeb", RanName).Return(nb, e2managererrors.NewRnibDbError())
239 err := manager.DissociateRan(E2TAddress, RanName)
241 assert.NotNil(t, err)
242 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
243 readerMock.AssertExpectations(t)
244 writerMock.AssertExpectations(t)
245 httpClientMock.AssertExpectations(t)
248 func TestDissociateRanUpdateNodebError(t *testing.T) {
249 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
250 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
251 readerMock.On("GetNodeb", RanName).Return(nb, nil)
253 updatedNb.AssociatedE2TInstanceAddress = ""
254 writerMock.On("UpdateNodebInfo", mock.Anything).Return(e2managererrors.NewRnibDbError())
256 err := manager.DissociateRan(E2TAddress, RanName)
258 assert.NotNil(t, err)
259 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
260 readerMock.AssertExpectations(t)
261 writerMock.AssertExpectations(t)
262 httpClientMock.AssertExpectations(t)
265 func TestDissociateRanGetE2tInstanceError(t *testing.T) {
266 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
267 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
268 readerMock.On("GetNodeb", RanName).Return(nb, nil)
270 updatedNb.AssociatedE2TInstanceAddress = ""
271 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
272 var e2tInstance *entities.E2TInstance
273 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
275 err := manager.DissociateRan(E2TAddress, RanName)
277 assert.NotNil(t, err)
278 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
279 readerMock.AssertExpectations(t)
280 writerMock.AssertExpectations(t)
281 httpClientMock.AssertExpectations(t)
284 func TestDissociateRanSaveE2tInstanceError(t *testing.T) {
285 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
286 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
287 readerMock.On("GetNodeb", RanName).Return(nb, nil)
289 updatedNb.AssociatedE2TInstanceAddress = ""
290 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
291 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
292 e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
293 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
294 updatedE2tInstance := *e2tInstance
295 updatedE2tInstance.AssociatedRanList = []string{}
296 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
298 err := manager.DissociateRan(E2TAddress, RanName)
300 assert.NotNil(t, err)
301 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
302 readerMock.AssertExpectations(t)
303 writerMock.AssertExpectations(t)
304 httpClientMock.AssertExpectations(t)
307 func TestDissociateRanRoutingManagerError(t *testing.T) {
308 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
309 mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, false)
310 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
311 readerMock.On("GetNodeb", RanName).Return(nb, nil)
313 updatedNb.AssociatedE2TInstanceAddress = ""
314 writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
315 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
316 e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
317 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
318 updatedE2tInstance := *e2tInstance
319 updatedE2tInstance.AssociatedRanList = []string{}
320 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
322 err := manager.DissociateRan(E2TAddress, RanName)
325 readerMock.AssertExpectations(t)
326 writerMock.AssertExpectations(t)
327 httpClientMock.AssertExpectations(t)
330 func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) {
331 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
333 ranNamesToBeDissociated := []string{RanName, "test1"}
334 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, ranNamesToBeDissociated, nil)
335 mockHttpClientDelete(httpClientMock, data, true)
337 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
338 e2tAddresses := []string{E2TAddress}
339 readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
340 e2tAddressesNew := []string{}
341 writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
343 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: ranNamesToBeDissociated}
344 err := manager.RemoveE2tInstance(e2tInstance1)
347 readerMock.AssertExpectations(t)
348 writerMock.AssertExpectations(t)
349 httpClientMock.AssertExpectations(t)
352 func TestRemoveE2tInstanceFailureRoutingManager(t *testing.T) {
353 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
355 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
356 mockHttpClientDelete(httpClientMock, data, false)
358 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
359 e2tAddresses := []string{E2TAddress}
360 readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
361 e2tAddressesNew := []string{}
362 writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
364 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"test1"}}
365 //readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewRnibDbError())
366 err := manager.RemoveE2tInstance(e2tInstance1)
369 readerMock.AssertExpectations(t)
370 writerMock.AssertExpectations(t)
371 httpClientMock.AssertExpectations(t)
374 func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) {
376 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
377 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
378 mockHttpClientDelete(httpClientMock, data, true)
380 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
381 var e2tAddresses []string
382 readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
384 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"test1"}}
385 err := manager.RemoveE2tInstance(e2tInstance1)
387 assert.NotNil(t, err)
388 readerMock.AssertExpectations(t)
389 writerMock.AssertExpectations(t)
390 httpClientMock.AssertExpectations(t)
393 func TestRemoveE2tInstanceFailureInE2tInstanceAddRansToInstance(t *testing.T) {
394 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
396 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil)
397 mockHttpClientDelete(httpClientMock, data, true)
399 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
400 e2tAddresses := []string{E2TAddress, E2TAddress2, E2TAddress3}
401 readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
402 e2tAddressesNew := []string{E2TAddress2, E2TAddress3}
403 writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
405 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress}
406 err := manager.RemoveE2tInstance(e2tInstance1)
409 readerMock.AssertExpectations(t)
410 writerMock.AssertExpectations(t)
411 httpClientMock.AssertExpectations(t)
414 func mockHttpClientDelete(httpClientMock *mocks.HttpClientMock, data *models.RoutingManagerDeleteRequestModel, isSuccessful bool) {
416 marshaled, _ := json.Marshal(data)
417 body := bytes.NewBuffer(marshaled)
418 respBody := ioutil.NopCloser(bytes.NewBufferString(""))
419 var respStatusCode int
421 respStatusCode = http.StatusCreated
423 respStatusCode = http.StatusBadRequest
425 httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)