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"
31 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
32 "github.com/pkg/errors"
33 "github.com/stretchr/testify/assert"
39 const RanName = "test"
41 func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
43 config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, StateChangeMessageChannel: "RAN_CONNECTION_STATUS_CHANGE"}
45 readerMock := &mocks.RnibReaderMock{}
46 writerMock := &mocks.RnibWriterMock{}
47 rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
49 e2tInstancesManager := NewE2TInstancesManager(rnibDataService, log)
50 httpClientMock := &mocks.HttpClientMock{}
51 rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
52 ranListManager := NewRanListManager(log)
53 ranAlarmService := services.NewRanAlarmService(log, config)
54 ranConnectStatusChangeManager := NewRanConnectStatusChangeManager(log, rnibDataService,ranListManager, ranAlarmService)
55 e2tAssociationManager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager)
56 return e2tAssociationManager, readerMock, writerMock, httpClientMock
59 func mockHttpClient(httpClientMock *mocks.HttpClientMock, apiSuffix string, isSuccessful bool) {
60 data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)}
61 marshaled, _ := json.Marshal(data)
62 body := bytes.NewBuffer(marshaled)
63 respBody := ioutil.NopCloser(bytes.NewBufferString(""))
64 var respStatusCode int
66 respStatusCode = http.StatusCreated
68 respStatusCode = http.StatusBadRequest
70 httpClientMock.On("Post", apiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
73 func TestAssociateRanSuccess(t *testing.T) {
74 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
75 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
76 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
78 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
79 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, "RAN_CONNECTION_STATUS_CHANGE", RanName+"_CONNECTED").Return(nil)
81 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
82 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
83 writerMock.On("UpdateNodebInfo", &updatedNb2).Return(nil)
84 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
85 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
86 updatedE2tInstance := *e2tInstance
87 updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
88 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
90 err := manager.AssociateRan(E2TAddress, nb)
93 readerMock.AssertExpectations(t)
94 writerMock.AssertExpectations(t)
95 httpClientMock.AssertExpectations(t)
98 func TestAssociateRanRoutingManagerError(t *testing.T) {
99 manager, _, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
100 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, false)
101 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
102 writerMock.On("UpdateNodebInfo", nb).Return(nil)
104 err := manager.AssociateRan(E2TAddress, nb)
106 assert.NotNil(t, err)
107 assert.IsType(t, &e2managererrors.RoutingManagerError{}, err)
108 writerMock.AssertExpectations(t)
109 httpClientMock.AssertExpectations(t)
112 func TestAssociateRanUpdateNodebError(t *testing.T) {
113 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
114 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
115 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
118 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
119 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, "RAN_CONNECTION_STATUS_CHANGE", RanName+"_CONNECTED").Return(nil)
121 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
122 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
123 writerMock.On("UpdateNodebInfo", &updatedNb2).Return(e2managererrors.NewRnibDbError())
125 err := manager.AssociateRan(E2TAddress, nb)
127 assert.NotNil(t, err)
128 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
129 readerMock.AssertExpectations(t)
130 writerMock.AssertExpectations(t)
131 httpClientMock.AssertExpectations(t)
134 func TestAssociateRanGetE2tInstanceError(t *testing.T) {
135 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
136 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
137 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
140 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
141 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, "RAN_CONNECTION_STATUS_CHANGE", RanName+"_CONNECTED").Return(nil)
144 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
145 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
146 writerMock.On("UpdateNodebInfo", &updatedNb2).Return(nil)
147 var e2tInstance *entities.E2TInstance
148 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
150 err := manager.AssociateRan(E2TAddress, nb)
152 assert.NotNil(t, err)
153 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
154 readerMock.AssertExpectations(t)
155 writerMock.AssertExpectations(t)
156 httpClientMock.AssertExpectations(t)
159 func TestAssociateRanSaveE2tInstanceError(t *testing.T) {
160 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
161 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
162 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
165 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
166 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, "RAN_CONNECTION_STATUS_CHANGE", RanName+"_CONNECTED").Return(nil)
169 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
170 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
171 writerMock.On("UpdateNodebInfo", &updatedNb2).Return(nil)
172 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
173 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
174 updatedE2tInstance := *e2tInstance
175 updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
176 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
178 err := manager.AssociateRan(E2TAddress, nb)
180 assert.NotNil(t, err)
181 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
182 readerMock.AssertExpectations(t)
183 writerMock.AssertExpectations(t)
184 httpClientMock.AssertExpectations(t)
187 func TestDissociateRanSuccess(t *testing.T) {
188 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
189 mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, true)
190 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
191 readerMock.On("GetNodeb", RanName).Return(nb, nil)
193 updatedNb.AssociatedE2TInstanceAddress = ""
194 writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
195 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
196 e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
197 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
198 updatedE2tInstance := *e2tInstance
199 updatedE2tInstance.AssociatedRanList = []string{}
200 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
202 err := manager.DissociateRan(E2TAddress, RanName)
205 readerMock.AssertExpectations(t)
206 writerMock.AssertExpectations(t)
207 httpClientMock.AssertExpectations(t)
210 func TestDissociateRanGetNodebError(t *testing.T) {
211 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
212 var nb *entities.NodebInfo
213 readerMock.On("GetNodeb", RanName).Return(nb, e2managererrors.NewRnibDbError())
215 err := manager.DissociateRan(E2TAddress, RanName)
217 assert.NotNil(t, err)
218 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
219 readerMock.AssertExpectations(t)
220 writerMock.AssertExpectations(t)
221 httpClientMock.AssertExpectations(t)
224 func TestDissociateRanUpdateNodebError(t *testing.T) {
225 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
226 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
227 readerMock.On("GetNodeb", RanName).Return(nb, nil)
229 updatedNb.AssociatedE2TInstanceAddress = ""
230 writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError())
232 err := manager.DissociateRan(E2TAddress, RanName)
234 assert.NotNil(t, err)
235 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
236 readerMock.AssertExpectations(t)
237 writerMock.AssertExpectations(t)
238 httpClientMock.AssertExpectations(t)
241 func TestDissociateRanGetE2tInstanceError(t *testing.T) {
242 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
243 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
244 readerMock.On("GetNodeb", RanName).Return(nb, nil)
246 updatedNb.AssociatedE2TInstanceAddress = ""
247 writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
248 var e2tInstance *entities.E2TInstance
249 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
251 err := manager.DissociateRan(E2TAddress, RanName)
253 assert.NotNil(t, err)
254 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
255 readerMock.AssertExpectations(t)
256 writerMock.AssertExpectations(t)
257 httpClientMock.AssertExpectations(t)
260 func TestDissociateRanSaveE2tInstanceError(t *testing.T) {
261 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
262 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
263 readerMock.On("GetNodeb", RanName).Return(nb, nil)
265 updatedNb.AssociatedE2TInstanceAddress = ""
266 writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
267 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
268 e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
269 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
270 updatedE2tInstance := *e2tInstance
271 updatedE2tInstance.AssociatedRanList = []string{}
272 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
274 err := manager.DissociateRan(E2TAddress, RanName)
276 assert.NotNil(t, err)
277 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
278 readerMock.AssertExpectations(t)
279 writerMock.AssertExpectations(t)
280 httpClientMock.AssertExpectations(t)
283 func TestDissociateRanRoutingManagerError(t *testing.T) {
284 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
285 mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, false)
286 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
287 readerMock.On("GetNodeb", RanName).Return(nb, nil)
289 updatedNb.AssociatedE2TInstanceAddress = ""
290 writerMock.On("UpdateNodebInfo", &updatedNb).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(nil)
298 err := manager.DissociateRan(E2TAddress, RanName)
301 readerMock.AssertExpectations(t)
302 writerMock.AssertExpectations(t)
303 httpClientMock.AssertExpectations(t)
306 func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) {
307 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
309 ranNamesToBeDissociated := []string{RanName, "test1"}
310 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, ranNamesToBeDissociated, nil)
311 mockHttpClientDelete(httpClientMock, data, true)
313 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
314 e2tAddresses := []string{E2TAddress}
315 readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
316 e2tAddressesNew := []string{}
317 writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
319 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:ranNamesToBeDissociated}
320 err := manager.RemoveE2tInstance(e2tInstance1)
323 readerMock.AssertExpectations(t)
324 writerMock.AssertExpectations(t)
325 httpClientMock.AssertExpectations(t)
328 func TestRemoveE2tInstanceFailureRoutingManager(t *testing.T) {
329 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
331 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
332 mockHttpClientDelete(httpClientMock, data, false)
334 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
335 e2tAddresses := []string{E2TAddress}
336 readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
337 e2tAddressesNew := []string{}
338 writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
340 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{"test1"}}
341 //readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewRnibDbError())
342 err := manager.RemoveE2tInstance(e2tInstance1)
345 readerMock.AssertExpectations(t)
346 writerMock.AssertExpectations(t)
347 httpClientMock.AssertExpectations(t)
350 func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) {
352 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
353 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
354 mockHttpClientDelete(httpClientMock, data, true)
356 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
357 var e2tAddresses []string
358 readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
360 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{"test1"}}
361 err := manager.RemoveE2tInstance(e2tInstance1)
363 assert.NotNil(t, err)
364 readerMock.AssertExpectations(t)
365 writerMock.AssertExpectations(t)
366 httpClientMock.AssertExpectations(t)
369 func TestRemoveE2tInstanceFailureInE2tInstanceAddRansToInstance(t *testing.T) {
370 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
372 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil)
373 mockHttpClientDelete(httpClientMock, data, true)
375 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
376 e2tAddresses := []string{E2TAddress, E2TAddress2, E2TAddress3}
377 readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
378 e2tAddressesNew := []string{E2TAddress2, E2TAddress3}
379 writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
381 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress}
382 err := manager.RemoveE2tInstance(e2tInstance1)
385 readerMock.AssertExpectations(t)
386 writerMock.AssertExpectations(t)
387 httpClientMock.AssertExpectations(t)
390 func mockHttpClientDelete(httpClientMock *mocks.HttpClientMock, data *models.RoutingManagerDeleteRequestModel, isSuccessful bool) {
392 marshaled, _ := json.Marshal(data)
393 body := bytes.NewBuffer(marshaled)
394 respBody := ioutil.NopCloser(bytes.NewBufferString(""))
395 var respStatusCode int
397 respStatusCode = http.StatusCreated
399 respStatusCode = http.StatusBadRequest
401 httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)