994dd407fb182714af94dbd1d8538026d6d0b382
[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         "github.com/stretchr/testify/mock"
35         "io/ioutil"
36         "net/http"
37         "testing"
38 )
39
40 const RanName = "test"
41
42 func initE2TAssociationManagerTest(t *testing.T) (*E2TAssociationManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
43         log := initLog(t)
44         config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3}
45
46         readerMock := &mocks.RnibReaderMock{}
47         writerMock := &mocks.RnibWriterMock{}
48         rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
49
50         e2tInstancesManager := NewE2TInstancesManager(rnibDataService, log)
51         httpClientMock := &mocks.HttpClientMock{}
52         rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
53         manager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient)
54
55         return manager, readerMock, writerMock, httpClientMock
56 }
57
58 func mockHttpClient(httpClientMock *mocks.HttpClientMock, apiSuffix string, isSuccessful bool) {
59         data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(E2TAddress, RanName)}
60         marshaled, _ := json.Marshal(data)
61         body := bytes.NewBuffer(marshaled)
62         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
63         var respStatusCode int
64         if isSuccessful {
65                 respStatusCode = http.StatusCreated
66         } else {
67                 respStatusCode = http.StatusBadRequest
68         }
69         httpClientMock.On("Post", apiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
70 }
71
72 func TestAssociateRanSuccess(t *testing.T) {
73         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
74         mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
75         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1}
76         updatedNb := *nb
77         updatedNb.ConnectionAttempts = 0
78         updatedNb.AssociatedE2TInstanceAddress = E2TAddress
79         writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
80         e2tInstance := &entities.E2TInstance{Address: E2TAddress}
81         readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
82         updatedE2tInstance := *e2tInstance
83         updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
84         writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
85
86         err := manager.AssociateRan(E2TAddress, nb)
87
88         assert.Nil(t, err)
89         readerMock.AssertExpectations(t)
90         writerMock.AssertExpectations(t)
91         httpClientMock.AssertExpectations(t)
92 }
93
94 func TestAssociateRanRoutingManagerError(t *testing.T) {
95         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
96         mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, false)
97         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1}
98         writerMock.On("UpdateNodebInfo", nb).Return(nil)
99         e2tInstance := &entities.E2TInstance{Address: E2TAddress}
100         readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
101         writerMock.On("SaveE2TInstance", mock.Anything).Return(nil)
102         err := manager.AssociateRan(E2TAddress, nb)
103
104         assert.Nil(t, err)
105         readerMock.AssertExpectations(t)
106         writerMock.AssertExpectations(t)
107         httpClientMock.AssertExpectations(t)
108 }
109
110 func TestAssociateRanUpdateNodebError(t *testing.T) {
111         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
112         //mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
113         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1}
114         updatedNb := *nb
115         updatedNb.ConnectionAttempts = 0
116         updatedNb.AssociatedE2TInstanceAddress = E2TAddress
117         writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError())
118
119         err := manager.AssociateRan(E2TAddress, nb)
120
121         assert.NotNil(t, err)
122         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
123         readerMock.AssertExpectations(t)
124         writerMock.AssertExpectations(t)
125         httpClientMock.AssertExpectations(t)
126 }
127
128 func TestAssociateRanGetE2tInstanceError(t *testing.T) {
129         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
130         //mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
131         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1}
132         updatedNb := *nb
133         updatedNb.ConnectionAttempts = 0
134         updatedNb.AssociatedE2TInstanceAddress = E2TAddress
135         writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
136         var e2tInstance *entities.E2TInstance
137         readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
138
139         err := manager.AssociateRan(E2TAddress, nb)
140
141         assert.NotNil(t, err)
142         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
143         readerMock.AssertExpectations(t)
144         writerMock.AssertExpectations(t)
145         httpClientMock.AssertExpectations(t)
146 }
147
148 func TestAssociateRanSaveE2tInstanceError(t *testing.T) {
149         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
150         //mockHttpClient(httpClientMock, clients.AssociateRanToE2TInstanceApiSuffix, true)
151         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: "", ConnectionAttempts: 1}
152         updatedNb := *nb
153         updatedNb.ConnectionAttempts = 0
154         updatedNb.AssociatedE2TInstanceAddress = E2TAddress
155         writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
156         e2tInstance := &entities.E2TInstance{Address: E2TAddress}
157         readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
158         updatedE2tInstance := *e2tInstance
159         updatedE2tInstance.AssociatedRanList = append(updatedE2tInstance.AssociatedRanList, RanName)
160         writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
161
162         err := manager.AssociateRan(E2TAddress, nb)
163
164         assert.NotNil(t, err)
165         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
166         readerMock.AssertExpectations(t)
167         writerMock.AssertExpectations(t)
168         httpClientMock.AssertExpectations(t)
169 }
170
171 func TestDissociateRanSuccess(t *testing.T) {
172         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
173         mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, true)
174         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1}
175         readerMock.On("GetNodeb", RanName).Return(nb, nil)
176         updatedNb := *nb
177         updatedNb.AssociatedE2TInstanceAddress = ""
178         writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
179         e2tInstance := &entities.E2TInstance{Address: E2TAddress}
180         e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
181         readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
182         updatedE2tInstance := *e2tInstance
183         updatedE2tInstance.AssociatedRanList = []string{}
184         writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
185
186         err := manager.DissociateRan(E2TAddress, RanName)
187
188         assert.Nil(t, err)
189         readerMock.AssertExpectations(t)
190         writerMock.AssertExpectations(t)
191         httpClientMock.AssertExpectations(t)
192 }
193
194 func TestDissociateRanGetNodebError(t *testing.T) {
195         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
196         var nb *entities.NodebInfo
197         readerMock.On("GetNodeb", RanName).Return(nb, e2managererrors.NewRnibDbError())
198
199         err := manager.DissociateRan(E2TAddress, RanName)
200
201         assert.NotNil(t, err)
202         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
203         readerMock.AssertExpectations(t)
204         writerMock.AssertExpectations(t)
205         httpClientMock.AssertExpectations(t)
206 }
207
208 func TestDissociateRanUpdateNodebError(t *testing.T) {
209         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
210         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1}
211         readerMock.On("GetNodeb", RanName).Return(nb, nil)
212         updatedNb := *nb
213         updatedNb.AssociatedE2TInstanceAddress = ""
214         writerMock.On("UpdateNodebInfo", &updatedNb).Return(e2managererrors.NewRnibDbError())
215
216         err := manager.DissociateRan(E2TAddress, RanName)
217
218         assert.NotNil(t, err)
219         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
220         readerMock.AssertExpectations(t)
221         writerMock.AssertExpectations(t)
222         httpClientMock.AssertExpectations(t)
223 }
224
225 func TestDissociateRanGetE2tInstanceError(t *testing.T) {
226         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
227         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1}
228         readerMock.On("GetNodeb", RanName).Return(nb, nil)
229         updatedNb := *nb
230         updatedNb.AssociatedE2TInstanceAddress = ""
231         writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
232         var e2tInstance *entities.E2TInstance
233         readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, errors.New("test"))
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 TestDissociateRanSaveE2tInstanceError(t *testing.T) {
245         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
246         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1}
247         readerMock.On("GetNodeb", RanName).Return(nb, nil)
248         updatedNb := *nb
249         updatedNb.AssociatedE2TInstanceAddress = ""
250         writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
251         e2tInstance := &entities.E2TInstance{Address: E2TAddress}
252         e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
253         readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
254         updatedE2tInstance := *e2tInstance
255         updatedE2tInstance.AssociatedRanList = []string{}
256         writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(errors.New("test"))
257
258         err := manager.DissociateRan(E2TAddress, RanName)
259
260         assert.NotNil(t, err)
261         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
262         readerMock.AssertExpectations(t)
263         writerMock.AssertExpectations(t)
264         httpClientMock.AssertExpectations(t)
265 }
266
267 func TestDissociateRanRoutingManagerError(t *testing.T) {
268         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
269         mockHttpClient(httpClientMock, clients.DissociateRanE2TInstanceApiSuffix, false)
270         nb := &entities.NodebInfo{RanName: RanName, AssociatedE2TInstanceAddress: E2TAddress, ConnectionAttempts: 1}
271         readerMock.On("GetNodeb", RanName).Return(nb, nil)
272         updatedNb := *nb
273         updatedNb.AssociatedE2TInstanceAddress = ""
274         writerMock.On("UpdateNodebInfo", &updatedNb).Return(nil)
275         e2tInstance := &entities.E2TInstance{Address: E2TAddress}
276         e2tInstance.AssociatedRanList = append(e2tInstance.AssociatedRanList, RanName)
277         readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance, nil)
278         updatedE2tInstance := *e2tInstance
279         updatedE2tInstance.AssociatedRanList = []string{}
280         writerMock.On("SaveE2TInstance", &updatedE2tInstance).Return(nil)
281
282         err := manager.DissociateRan(E2TAddress, RanName)
283
284         assert.Nil(t, err)
285         readerMock.AssertExpectations(t)
286         writerMock.AssertExpectations(t)
287         httpClientMock.AssertExpectations(t)
288 }
289
290 func TestRemoveE2tInstanceSuccessWithOrphans(t *testing.T) {
291         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
292
293         ranNamesToBeDissociated := []string{RanName, "test1"}
294         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, ranNamesToBeDissociated, nil)
295         mockHttpClientDelete(httpClientMock, data, true)
296
297         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
298         e2tAddresses := []string{E2TAddress}
299         readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
300         e2tAddressesNew := []string{}
301         writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
302
303         e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:ranNamesToBeDissociated}
304         err := manager.RemoveE2tInstance(e2tInstance1)
305
306         assert.Nil(t, err)
307         readerMock.AssertExpectations(t)
308         writerMock.AssertExpectations(t)
309         httpClientMock.AssertExpectations(t)
310 }
311
312 func TestRemoveE2tInstanceFailureRoutingManager(t *testing.T) {
313         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
314
315         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
316         mockHttpClientDelete(httpClientMock, data, false)
317
318         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
319         e2tAddresses := []string{E2TAddress}
320         readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
321         e2tAddressesNew := []string{}
322         writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
323
324         e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{"test1"}}
325         //readerMock.On("GetE2TInstance", E2TAddress).Return(e2tInstance1, e2managererrors.NewRnibDbError())
326         err := manager.RemoveE2tInstance(e2tInstance1)
327
328         assert.Nil(t, err)
329         readerMock.AssertExpectations(t)
330         writerMock.AssertExpectations(t)
331         httpClientMock.AssertExpectations(t)
332 }
333
334 func TestRemoveE2tInstanceFailureInE2TInstanceManager(t *testing.T) {
335
336         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1"}, nil)
337         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
338         mockHttpClientDelete(httpClientMock, data, true)
339
340         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
341         var e2tAddresses []string
342         readerMock.On("GetE2TAddresses").Return(e2tAddresses, e2managererrors.NewRnibDbError())
343
344         e2tInstance1 := &entities.E2TInstance{Address: E2TAddress, AssociatedRanList:[]string{"test1"}}
345         err := manager.RemoveE2tInstance(e2tInstance1)
346
347         assert.NotNil(t, err)
348         readerMock.AssertExpectations(t)
349         writerMock.AssertExpectations(t)
350         httpClientMock.AssertExpectations(t)
351 }
352
353 func TestRemoveE2tInstanceFailureInE2tInstanceAddRansToInstance(t *testing.T) {
354         manager, readerMock, writerMock, httpClientMock := initE2TAssociationManagerTest(t)
355
356         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil)
357         mockHttpClientDelete(httpClientMock, data, true)
358
359         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
360         e2tAddresses := []string{E2TAddress, E2TAddress2, E2TAddress3}
361         readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
362         e2tAddressesNew := []string{E2TAddress2, E2TAddress3}
363         writerMock.On("SaveE2TAddresses", e2tAddressesNew).Return(nil)
364
365         e2tInstance1 := &entities.E2TInstance{Address: E2TAddress}
366         err := manager.RemoveE2tInstance(e2tInstance1)
367
368         assert.Nil(t, err)
369         readerMock.AssertExpectations(t)
370         writerMock.AssertExpectations(t)
371         httpClientMock.AssertExpectations(t)
372 }
373
374 func mockHttpClientDelete(httpClientMock *mocks.HttpClientMock, data *models.RoutingManagerDeleteRequestModel, isSuccessful bool) {
375
376         marshaled, _ := json.Marshal(data)
377         body := bytes.NewBuffer(marshaled)
378         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
379         var respStatusCode int
380         if isSuccessful {
381                 respStatusCode = http.StatusCreated
382         } else {
383                 respStatusCode = http.StatusBadRequest
384         }
385         httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
386 }