[RIC-475] Enhance and refactor E2 Setup UTs
[ric-plt/e2mgr.git] / E2Manager / managers / e2t_association_manager_test.go
1 //
2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
4 //
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
8 //
9 //      http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16
17 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 //  platform project (RICP).
19
20 package managers
21
22 import (
23         "bytes"
24         "e2mgr/clients"
25         "e2mgr/configuration"
26         "e2mgr/e2managererrors"
27         "e2mgr/mocks"
28         "e2mgr/models"
29         "e2mgr/services"
30         "encoding/json"
31         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
32         "github.com/pkg/errors"
33         "github.com/stretchr/testify/assert"
34         "io/ioutil"
35         "net/http"
36         "testing"
37 )
38
39 const (
40         RanName                   = "test"
41         StateChangeMessageChannel = "RAN_CONNECTION_STATUS_CHANGE"
42 )
43
44 func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
45         log := initLog(t)
46         config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, StateChangeMessageChannel: StateChangeMessageChannel}
47
48         readerMock := &mocks.RnibReaderMock{}
49         writerMock := &mocks.RnibWriterMock{}
50         rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
51
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
60 }
61
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
68         if isSuccessful {
69                 respStatusCode = http.StatusCreated
70         } else {
71                 respStatusCode = http.StatusBadRequest
72         }
73         httpClientMock.On("Post", apiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
74 }
75
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: ""}
80         updatedNb := *nb
81         updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
82         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, StateChangeMessageChannel, RanName+"_CONNECTED").Return(nil)
83         updatedNb2 := *nb
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)
92
93         err := manager.AssociateRan(E2TAddress, nb)
94
95         assert.Nil(t, err)
96         readerMock.AssertExpectations(t)
97         writerMock.AssertExpectations(t)
98         httpClientMock.AssertExpectations(t)
99 }
100
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)
106
107         err := manager.AssociateRan(E2TAddress, nb)
108
109         assert.NotNil(t, err)
110         assert.IsType(t, &e2managererrors.RoutingManagerError{}, err)
111         writerMock.AssertExpectations(t)
112         httpClientMock.AssertExpectations(t)
113 }
114
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: ""}
119
120         updatedNb := *nb
121         updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
122         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, StateChangeMessageChannel, RanName+"_CONNECTED").Return(nil)
123         updatedNb2 := *nb
124         updatedNb2.ConnectionStatus = entities.ConnectionStatus_CONNECTED
125         updatedNb2.AssociatedE2TInstanceAddress = E2TAddress
126         writerMock.On("UpdateNodebInfo", &updatedNb2).Return(e2managererrors.NewRnibDbError())
127
128         err := manager.AssociateRan(E2TAddress, nb)
129
130         assert.NotNil(t, err)
131         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
132         readerMock.AssertExpectations(t)
133         writerMock.AssertExpectations(t)
134         httpClientMock.AssertExpectations(t)
135 }
136
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: ""}
141
142         updatedNb := *nb
143         updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
144         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, StateChangeMessageChannel, RanName+"_CONNECTED").Return(nil)
145
146         updatedNb2 := *nb
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"))
152
153         err := manager.AssociateRan(E2TAddress, nb)
154
155         assert.NotNil(t, err)
156         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
157         readerMock.AssertExpectations(t)
158         writerMock.AssertExpectations(t)
159         httpClientMock.AssertExpectations(t)
160 }
161
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: ""}
166
167         updatedNb := *nb
168         updatedNb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
169         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", &updatedNb, StateChangeMessageChannel, RanName+"_CONNECTED").Return(nil)
170
171         updatedNb2 := *nb
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"))
180
181         err := manager.AssociateRan(E2TAddress, nb)
182
183         assert.NotNil(t, err)
184         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
185         readerMock.AssertExpectations(t)
186         writerMock.AssertExpectations(t)
187         httpClientMock.AssertExpectations(t)
188 }
189
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)
195         updatedNb := *nb
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)
204
205         err := manager.DissociateRan(E2TAddress, RanName)
206
207         assert.Nil(t, err)
208         readerMock.AssertExpectations(t)
209         writerMock.AssertExpectations(t)
210         httpClientMock.AssertExpectations(t)
211 }
212
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())
217
218         err := manager.DissociateRan(E2TAddress, RanName)
219
220         assert.NotNil(t, err)
221         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
222         readerMock.AssertExpectations(t)
223         writerMock.AssertExpectations(t)
224         httpClientMock.AssertExpectations(t)
225 }
226
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)
231         updatedNb := *nb
232         updatedNb.AssociatedE2TInstanceAddress = ""
233         writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError())
234
235         err := manager.DissociateRan(E2TAddress, RanName)
236
237         assert.NotNil(t, err)
238         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
239         readerMock.AssertExpectations(t)
240         writerMock.AssertExpectations(t)
241         httpClientMock.AssertExpectations(t)
242 }
243
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)
248         updatedNb := *nb
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"))
253
254         err := manager.DissociateRan(E2TAddress, RanName)
255
256         assert.NotNil(t, err)
257         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
258         readerMock.AssertExpectations(t)
259         writerMock.AssertExpectations(t)
260         httpClientMock.AssertExpectations(t)
261 }
262
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)
267         updatedNb := *nb
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"))
276
277         err := manager.DissociateRan(E2TAddress, RanName)
278
279         assert.NotNil(t, err)
280         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
281         readerMock.AssertExpectations(t)
282         writerMock.AssertExpectations(t)
283         httpClientMock.AssertExpectations(t)
284 }
285
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)
291         updatedNb := *nb
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)
300
301         err := manager.DissociateRan(E2TAddress, RanName)
302
303         assert.Nil(t, err)
304         readerMock.AssertExpectations(t)
305         writerMock.AssertExpectations(t)
306         httpClientMock.AssertExpectations(t)
307 }
308
309 func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) {
310         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
311
312         ranNamesToBeDissociated := []string{RanName, "test1"}
313         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, ranNamesToBeDissociated, nil)
314         mockHttpClientDelete(httpClientMock, data, true)
315
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)
321
322         e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: ranNamesToBeDissociated}
323         err := manager.RemoveE2tInstance(e2tInstance1)
324
325         assert.Nil(t, err)
326         readerMock.AssertExpectations(t)
327         writerMock.AssertExpectations(t)
328         httpClientMock.AssertExpectations(t)
329 }
330
331 func TestRemoveE2tInstanceFailureRoutingManager(t *testing.T) {
332         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
333
334         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
335         mockHttpClientDelete(httpClientMock, data, false)
336
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)
342
343         e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"test1"}}
344         //readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewRnibDbError())
345         err := manager.RemoveE2tInstance(e2tInstance1)
346
347         assert.Nil(t, err)
348         readerMock.AssertExpectations(t)
349         writerMock.AssertExpectations(t)
350         httpClientMock.AssertExpectations(t)
351 }
352
353 func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) {
354
355         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
356         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
357         mockHttpClientDelete(httpClientMock, data, true)
358
359         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
360         var e2tAddresses []string
361         readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
362
363         e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList: []string{"test1"}}
364         err := manager.RemoveE2tInstance(e2tInstance1)
365
366         assert.NotNil(t, err)
367         readerMock.AssertExpectations(t)
368         writerMock.AssertExpectations(t)
369         httpClientMock.AssertExpectations(t)
370 }
371
372 func TestRemoveE2tInstanceFailureInE2tInstanceAddRansToInstance(t *testing.T) {
373         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
374
375         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil)
376         mockHttpClientDelete(httpClientMock, data, true)
377
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)
383
384         e2tInstance1 := &entities.E2TInstance{Address: E2TAddress}
385         err := manager.RemoveE2tInstance(e2tInstance1)
386
387         assert.Nil(t, err)
388         readerMock.AssertExpectations(t)
389         writerMock.AssertExpectations(t)
390         httpClientMock.AssertExpectations(t)
391 }
392
393 func mockHttpClientDelete(httpClientMock *mocks.HttpClientMock, data *models.RoutingManagerDeleteRequestModel, isSuccessful bool) {
394
395         marshaled, _ := json.Marshal(data)
396         body := bytes.NewBuffer(marshaled)
397         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
398         var respStatusCode int
399         if isSuccessful {
400                 respStatusCode = http.StatusCreated
401         } else {
402                 respStatusCode = http.StatusBadRequest
403         }
404         httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
405 }