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