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