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"
41 StateChangeMessageChannel = "RAN_CONNECTION_STATUS_CHANGE"
44 func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
46 config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, StateChangeMessageChannel: StateChangeMessageChannel}
48 readerMock := &mocks.RnibReaderMock{}
49 writerMock := &mocks.RnibWriterMock{}
50 rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
52 e2tInstancesManager := NewE2TInstancesManager(rnibDataService, log)
53 httpClientMock := &mocks.HttpClientMock{}
54 rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
55 ranListManager := NewRanListManager(log)
56 ranAlarmService := services.NewRanAlarmService(log, config)
57 ranConnectStatusChangeManager := NewRanConnectStatusChangeManager(log, rnibDataService, ranListManager, ranAlarmService)
58 e2tAssociationManager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager)
59 return e2tAssociationManager, readerMock, writerMock, httpClientMock
62 func mockHttpClient(httpClientMock *mocks.HttpClientMock, apiSuffix string, isSuccessful bool) {
63 data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)}
64 marshaled, _ := json.Marshal(data)
65 body := bytes.NewBuffer(marshaled)
66 respBody := ioutil.NopCloser(bytes.NewBufferString(""))
67 var respStatusCode int
69 respStatusCode = http.StatusCreated
71 respStatusCode = http.StatusBadRequest
73 httpClientMock.On("Post", apiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
76 func TestAssociateRanSuccess(t *testing.T) {
77 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
78 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
79 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
81 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
82 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, StateChangeMessageChannel, RanName+"_CONNECTED").Return(nil)
84 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
85 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
86 writerMock.On("UpdateNodebInfo", &updatedNb2).Return(nil)
87 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
88 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
89 updatedE2tInstance := *e2tInstance
90 updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
91 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
93 err := manager.AssociateRan(E2TAddress, nb)
96 readerMock.AssertExpectations(t)
97 writerMock.AssertExpectations(t)
98 httpClientMock.AssertExpectations(t)
101 func TestAssociateRanRoutingManagerError(t *testing.T) {
102 manager, _, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
103 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, false)
104 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
105 writerMock.On("UpdateNodebInfo", nb).Return(nil)
107 err := manager.AssociateRan(E2TAddress, nb)
109 assert.NotNil(t, err)
110 assert.IsType(t, &e2managererrors.RoutingManagerError{}, err)
111 writerMock.AssertExpectations(t)
112 httpClientMock.AssertExpectations(t)
115 func TestAssociateRanUpdateNodebError(t *testing.T) {
116 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
117 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
118 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
121 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
122 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, StateChangeMessageChannel, RanName+"_CONNECTED").Return(nil)
124 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
125 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
126 writerMock.On("UpdateNodebInfo", &updatedNb2).Return(e2managererrors.NewRnibDbError())
128 err := manager.AssociateRan(E2TAddress, nb)
130 assert.NotNil(t, err)
131 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
132 readerMock.AssertExpectations(t)
133 writerMock.AssertExpectations(t)
134 httpClientMock.AssertExpectations(t)
137 func TestAssociateRanGetE2tInstanceError(t *testing.T) {
138 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
139 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
140 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
143 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
144 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, StateChangeMessageChannel, RanName+"_CONNECTED").Return(nil)
147 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
148 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
149 writerMock.On("UpdateNodebInfo", &updatedNb2).Return(nil)
150 var e2tInstance *entities.E2TInstance
151 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
153 err := manager.AssociateRan(E2TAddress, nb)
155 assert.NotNil(t, err)
156 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
157 readerMock.AssertExpectations(t)
158 writerMock.AssertExpectations(t)
159 httpClientMock.AssertExpectations(t)
162 func TestAssociateRanSaveE2tInstanceError(t *testing.T) {
163 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
164 mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
165 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: ""}
168 updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
169 writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, StateChangeMessageChannel, RanName+"_CONNECTED").Return(nil)
172 updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
173 updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
174 writerMock.On("UpdateNodebInfo", &updatedNb2).Return(nil)
175 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
176 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
177 updatedE2tInstance := *e2tInstance
178 updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
179 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
181 err := manager.AssociateRan(E2TAddress, nb)
183 assert.NotNil(t, err)
184 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
185 readerMock.AssertExpectations(t)
186 writerMock.AssertExpectations(t)
187 httpClientMock.AssertExpectations(t)
190 func TestDissociateRanSuccess(t *testing.T) {
191 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
192 mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, true)
193 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
194 readerMock.On("GetNodeb", RanName).Return(nb, nil)
196 updatedNb.AssociatedE2TInstanceAddress = ""
197 writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
198 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
199 e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
200 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
201 updatedE2tInstance := *e2tInstance
202 updatedE2tInstance.AssociatedRanList = []string{}
203 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
205 err := manager.DissociateRan(E2TAddress, RanName)
208 readerMock.AssertExpectations(t)
209 writerMock.AssertExpectations(t)
210 httpClientMock.AssertExpectations(t)
213 func TestDissociateRanGetNodebError(t *testing.T) {
214 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
215 var nb *entities.NodebInfo
216 readerMock.On("GetNodeb", RanName).Return(nb, e2managererrors.NewRnibDbError())
218 err := manager.DissociateRan(E2TAddress, RanName)
220 assert.NotNil(t, err)
221 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
222 readerMock.AssertExpectations(t)
223 writerMock.AssertExpectations(t)
224 httpClientMock.AssertExpectations(t)
227 func TestDissociateRanUpdateNodebError(t *testing.T) {
228 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
229 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
230 readerMock.On("GetNodeb", RanName).Return(nb, nil)
232 updatedNb.AssociatedE2TInstanceAddress = ""
233 writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError())
235 err := manager.DissociateRan(E2TAddress, RanName)
237 assert.NotNil(t, err)
238 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
239 readerMock.AssertExpectations(t)
240 writerMock.AssertExpectations(t)
241 httpClientMock.AssertExpectations(t)
244 func TestDissociateRanGetE2tInstanceError(t *testing.T) {
245 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
246 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
247 readerMock.On("GetNodeb", RanName).Return(nb, nil)
249 updatedNb.AssociatedE2TInstanceAddress = ""
250 writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
251 var e2tInstance *entities.E2TInstance
252 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
254 err := manager.DissociateRan(E2TAddress, RanName)
256 assert.NotNil(t, err)
257 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
258 readerMock.AssertExpectations(t)
259 writerMock.AssertExpectations(t)
260 httpClientMock.AssertExpectations(t)
263 func TestDissociateRanSaveE2tInstanceError(t *testing.T) {
264 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
265 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
266 readerMock.On("GetNodeb", RanName).Return(nb, nil)
268 updatedNb.AssociatedE2TInstanceAddress = ""
269 writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
270 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
271 e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
272 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
273 updatedE2tInstance := *e2tInstance
274 updatedE2tInstance.AssociatedRanList = []string{}
275 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
277 err := manager.DissociateRan(E2TAddress, RanName)
279 assert.NotNil(t, err)
280 assert.IsType(t, &e2managererrors.RnibDbError{}, err)
281 readerMock.AssertExpectations(t)
282 writerMock.AssertExpectations(t)
283 httpClientMock.AssertExpectations(t)
286 func TestDissociateRanRoutingManagerError(t *testing.T) {
287 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
288 mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, false)
289 nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress}
290 readerMock.On("GetNodeb", RanName).Return(nb, nil)
292 updatedNb.AssociatedE2TInstanceAddress = ""
293 writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
294 e2tInstance := &entities.E2TInstance{Address: E2TAddress}
295 e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
296 readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
297 updatedE2tInstance := *e2tInstance
298 updatedE2tInstance.AssociatedRanList = []string{}
299 writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
301 err := manager.DissociateRan(E2TAddress, RanName)
304 readerMock.AssertExpectations(t)
305 writerMock.AssertExpectations(t)
306 httpClientMock.AssertExpectations(t)
309 func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) {
310 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
312 ranNamesToBeDissociated := []string{RanName, "test1"}
313 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, ranNamesToBeDissociated, nil)
314 mockHttpClientDelete(httpClientMock, data, true)
316 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
317 e2tAddresses := []string{E2TAddress}
318 readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
319 e2tAddressesNew := []string{}
320 writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
322 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: ranNamesToBeDissociated}
323 err := manager.RemoveE2tInstance(e2tInstance1)
326 readerMock.AssertExpectations(t)
327 writerMock.AssertExpectations(t)
328 httpClientMock.AssertExpectations(t)
331 func TestRemoveE2tInstanceFailureRoutingManager(t *testing.T) {
332 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
334 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
335 mockHttpClientDelete(httpClientMock, data, false)
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: []string{"test1"}}
344 //readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewRnibDbError())
345 err := manager.RemoveE2tInstance(e2tInstance1)
348 readerMock.AssertExpectations(t)
349 writerMock.AssertExpectations(t)
350 httpClientMock.AssertExpectations(t)
353 func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) {
355 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
356 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
357 mockHttpClientDelete(httpClientMock, data, true)
359 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
360 var e2tAddresses []string
361 readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
363 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"test1"}}
364 err := manager.RemoveE2tInstance(e2tInstance1)
366 assert.NotNil(t, err)
367 readerMock.AssertExpectations(t)
368 writerMock.AssertExpectations(t)
369 httpClientMock.AssertExpectations(t)
372 func TestRemoveE2tInstanceFailureInE2tInstanceAddRansToInstance(t *testing.T) {
373 manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
375 data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil)
376 mockHttpClientDelete(httpClientMock, data, true)
378 writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
379 e2tAddresses := []string{E2TAddress, E2TAddress2, E2TAddress3}
380 readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
381 e2tAddressesNew := []string{E2TAddress2, E2TAddress3}
382 writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
384 e2tInstance1 := &entities.E2TInstance{Address: E2TAddress}
385 err := manager.RemoveE2tInstance(e2tInstance1)
388 readerMock.AssertExpectations(t)
389 writerMock.AssertExpectations(t)
390 httpClientMock.AssertExpectations(t)
393 func mockHttpClientDelete(httpClientMock *mocks.HttpClientMock, data *models.RoutingManagerDeleteRequestModel, isSuccessful bool) {
395 marshaled, _ := json.Marshal(data)
396 body := bytes.NewBuffer(marshaled)
397 respBody := ioutil.NopCloser(bytes.NewBufferString(""))
398 var respStatusCode int
400 respStatusCode = http.StatusCreated
402 respStatusCode = http.StatusBadRequest
404 httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)