RIC916 new reconnect timer in E2 to reject new connect for x seconds
[ric-plt/e2mgr.git] / E2Manager / managers / e2t_shutdown_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
18 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
19 //  platform project (RICP).
20
21 package managers
22
23 import (
24         "bytes"
25         "e2mgr/clients"
26         "e2mgr/configuration"
27         "e2mgr/e2managererrors"
28         "e2mgr/mocks"
29         "e2mgr/models"
30         "e2mgr/services"
31         "encoding/json"
32         "fmt"
33         "io/ioutil"
34
35         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
36         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
37         "github.com/stretchr/testify/assert"
38         "github.com/stretchr/testify/mock"
39
40         //"k8s.io/apimachinery/pkg/runtime"
41         //"k8s.io/client-go/kubernetes/fake"
42         "net/http"
43         "testing"
44         "time"
45 )
46
47 const E2TAddress3 = "10.10.2.17:9800"
48
49 func initE2TShutdownManagerTest(t *testing.T) (*E2TShutdownManager, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
50         log := initLog(t)
51         config := &configuration.Configuration{RnibRetryIntervalMs: 10, MaxRnibConnectionAttempts: 3, E2TInstanceDeletionTimeoutMs: 15000, RnibWriter: configuration.RnibWriterConfig{StateChangeMessageChannel: "RAN_CONNECTION_STATUS_CHANGE"}}
52
53         readerMock := &mocks.RnibReaderMock{}
54         writerMock := &mocks.RnibWriterMock{}
55         rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
56
57         e2tInstancesManager := NewE2TInstancesManager(rnibDataService, log)
58         httpClientMock := &mocks.HttpClientMock{}
59         rmClient := clients.NewRoutingManagerClient(log, config, httpClientMock)
60
61         ranListManager := NewRanListManager(log, rnibDataService)
62         ranAlarmService := services.NewRanAlarmService(log, config)
63         ranConnectStatusChangeManager := NewRanConnectStatusChangeManager(log, rnibDataService, ranListManager, ranAlarmService)
64         associationManager := NewE2TAssociationManager(log, rnibDataService, e2tInstancesManager, rmClient, ranConnectStatusChangeManager)
65         shutdownManager := NewE2TShutdownManager(log, config, rnibDataService, e2tInstancesManager, associationManager, ranConnectStatusChangeManager)
66
67         return shutdownManager, readerMock, writerMock, httpClientMock
68 }
69
70 func TestShutdownSuccess1OutOf3Instances(t *testing.T) {
71         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
72
73         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
74         e2tInstance1.State = entities.Active
75         e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
76         e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
77         e2tInstance2.State = entities.Active
78         e2tInstance2.AssociatedRanList = []string{"test3"}
79         e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
80         e2tInstance3.State = entities.Active
81         e2tInstance3.AssociatedRanList = []string{"test4"}
82         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
83                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
84         })).Return(nil)
85
86         nodeb1 := &entities.NodebInfo{RanName: "test1", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
87         readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
88         nodeb2 := &entities.NodebInfo{RanName: "test2", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
89         readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
90         nodeb5 := &entities.NodebInfo{RanName: "test5", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
91         readerMock.On("GetNodeb", "test5").Return(nodeb5, nil)
92
93         e2tAddresses := []string{E2TAddress, E2TAddress2, E2TAddress3}
94         readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
95
96         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil)
97         marshaled, _ := json.Marshal(data)
98         body := bytes.NewBuffer(marshaled)
99         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
100         httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
101
102         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
103         writerMock.On("SaveE2TAddresses", []string{E2TAddress2, E2TAddress3}).Return(nil)
104
105         /*** nodeb 1 ***/
106         nodeb1connected := *nodeb1
107         nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
108         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test1_DISCONNECTED").Return(nil)
109
110         nodeb1NotAssociated := *nodeb1
111         nodeb1NotAssociated.AssociatedE2TInstanceAddress = ""
112         nodeb1NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
113         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
114
115         /*** nodeb 2 ***/
116         nodeb2connected := *nodeb2
117         nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
118         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
119
120         nodeb2NotAssociated := *nodeb2
121         nodeb2NotAssociated.AssociatedE2TInstanceAddress = ""
122         nodeb2NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
123         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
124
125         /*** nodeb 5 ***/
126         nodeb5connected := *nodeb5
127         nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
128         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test5_DISCONNECTED").Return(nil)
129
130         nodeb5NotAssociated := *nodeb5
131         nodeb5NotAssociated.AssociatedE2TInstanceAddress = ""
132         nodeb5NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
133         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
134
135         err := shutdownManager.Shutdown(e2tInstance1)
136
137         assert.Nil(t, err)
138         readerMock.AssertExpectations(t)
139         writerMock.AssertExpectations(t)
140         httpClientMock.AssertExpectations(t)
141 }
142
143 func TestShutdownSuccess1InstanceWithoutRans(t *testing.T) {
144         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
145
146         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
147         e2tInstance1.State = entities.Active
148         e2tInstance1.AssociatedRanList = []string{}
149         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
150                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
151         })).Return(nil)
152
153         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, nil, nil)
154         marshaled, _ := json.Marshal(data)
155         body := bytes.NewBuffer(marshaled)
156         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
157         httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
158
159         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
160         readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
161         writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
162
163         err := shutdownManager.Shutdown(e2tInstance1)
164
165         assert.Nil(t, err)
166         readerMock.AssertExpectations(t)
167         writerMock.AssertExpectations(t)
168         httpClientMock.AssertExpectations(t)
169 }
170
171 func TestShutdownSuccess1Instance2Rans(t *testing.T) {
172         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
173
174         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
175         e2tInstance1.State = entities.Active
176         e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
177         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
178                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
179         })).Return(nil)
180
181         nodeb1 := &entities.NodebInfo{RanName: "test1", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
182         readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
183         nodeb2 := &entities.NodebInfo{RanName: "test2", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
184         readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
185
186         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1", "test2"}, nil)
187         marshaled, _ := json.Marshal(data)
188         body := bytes.NewBuffer(marshaled)
189         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
190         httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
191
192         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
193         readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
194         writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
195
196         /*** nodeb 1 connected ***/
197         nodeb1new := *nodeb1
198         nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
199         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test1_DISCONNECTED").Return(nil)
200
201         nodeb1NotAssociated := *nodeb1
202         nodeb1NotAssociated.AssociatedE2TInstanceAddress = ""
203         nodeb1NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
204         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
205
206         /*** nodeb 2 disconnected ***/
207         nodeb2new := *nodeb2
208         nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
209         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
210
211         nodeb2NotAssociated := *nodeb2
212         nodeb2NotAssociated.AssociatedE2TInstanceAddress = ""
213         nodeb2NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
214         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
215
216         err := shutdownManager.Shutdown(e2tInstance1)
217
218         assert.Nil(t, err)
219         readerMock.AssertExpectations(t)
220         writerMock.AssertExpectations(t)
221         httpClientMock.AssertExpectations(t)
222 }
223
224 func TestShutdownE2tInstanceAlreadyBeingDeleted(t *testing.T) {
225         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
226
227         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
228         e2tInstance1.State = entities.ToBeDeleted
229         e2tInstance1.AssociatedRanList = []string{"test1"}
230         e2tInstance1.DeletionTimestamp = time.Now().UnixNano()
231
232         err := shutdownManager.Shutdown(e2tInstance1)
233
234         assert.Nil(t, err)
235         readerMock.AssertExpectations(t)
236         writerMock.AssertExpectations(t)
237         httpClientMock.AssertExpectations(t)
238 }
239
240 func TestShutdownFailureMarkInstanceAsToBeDeleted(t *testing.T) {
241         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
242
243         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
244         e2tInstance1.State = entities.Active
245         e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
246         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
247                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
248         })).Return(e2managererrors.NewRnibDbError())
249
250         err := shutdownManager.Shutdown(e2tInstance1)
251
252         assert.NotNil(t, err)
253         readerMock.AssertExpectations(t)
254         writerMock.AssertExpectations(t)
255         httpClientMock.AssertExpectations(t)
256 }
257
258 func TestShutdownFailureRoutingManagerError(t *testing.T) {
259         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
260
261         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
262         e2tInstance1.State = entities.Active
263         e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
264         e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
265         e2tInstance2.State = entities.Active
266         e2tInstance2.AssociatedRanList = []string{"test3"}
267         e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
268         e2tInstance3.State = entities.Active
269         e2tInstance3.AssociatedRanList = []string{"test4"}
270         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
271                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
272         })).Return(nil)
273
274         nodeb1 := &entities.NodebInfo{RanName: "test1", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
275         readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
276         nodeb2 := &entities.NodebInfo{RanName: "test2", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
277         readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
278         nodeb5 := &entities.NodebInfo{RanName: "test5", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
279         readerMock.On("GetNodeb", "test5").Return(nodeb5, nil)
280
281         e2tAddresses := []string{E2TAddress, E2TAddress2, E2TAddress3}
282         readerMock.On("GetE2TAddresses").Return(e2tAddresses, nil)
283
284         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil)
285         marshaled, _ := json.Marshal(data)
286         body := bytes.NewBuffer(marshaled)
287         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
288         httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusBadRequest, Body: respBody}, nil)
289
290         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
291         writerMock.On("SaveE2TAddresses", []string{E2TAddress2, E2TAddress3}).Return(nil)
292
293         /*** nodeb 1 connected ***/
294         nodeb1connected := *nodeb1
295         nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
296         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test1_DISCONNECTED").Return(nil)
297
298         nodeb1NotAssociated := *nodeb1
299         nodeb1NotAssociated.AssociatedE2TInstanceAddress = ""
300         nodeb1NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
301         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
302
303         /*** nodeb 2 shutting down ***/
304         nodeb2connected := *nodeb2
305         nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
306         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
307
308         nodeb2NotAssociated := *nodeb2
309         nodeb2NotAssociated.AssociatedE2TInstanceAddress = ""
310         nodeb2NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
311         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
312
313         /*** nodeb 5 connected ***/
314         nodeb5connected := *nodeb5
315         nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
316         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test5_DISCONNECTED").Return(nil)
317
318         nodeb5NotAssociated := *nodeb5
319         nodeb5NotAssociated.AssociatedE2TInstanceAddress = ""
320         nodeb5NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
321         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
322
323         err := shutdownManager.Shutdown(e2tInstance1)
324
325         assert.Nil(t, err)
326         readerMock.AssertExpectations(t)
327         writerMock.AssertExpectations(t)
328         httpClientMock.AssertExpectations(t)
329 }
330
331 func TestShutdownFailureInClearNodebsAssociation(t *testing.T) {
332         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
333
334         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
335         e2tInstance1.State = entities.Active
336         e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
337         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
338                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
339         })).Return(nil)
340
341         nodeb1 := &entities.NodebInfo{RanName: "test1", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
342         readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
343
344         nodeb1new := *nodeb1
345         nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
346         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test1_DISCONNECTED").Return(nil)
347
348         nodeb1NotAssociated := *nodeb1
349         nodeb1NotAssociated.AssociatedE2TInstanceAddress = ""
350         nodeb1NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
351         writerMock.On("UpdateNodebInfo", mock.Anything).Return(common.NewInternalError(fmt.Errorf("for tests")))
352
353         err := shutdownManager.Shutdown(e2tInstance1)
354
355         assert.NotNil(t, err)
356         readerMock.AssertExpectations(t)
357         writerMock.AssertExpectations(t)
358         httpClientMock.AssertExpectations(t)
359 }
360
361 func TestShutdownFailureInClearNodebsAssociation_UpdateConnectionStatus(t *testing.T) {
362         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
363
364         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
365         e2tInstance1.State = entities.Active
366         e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
367         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
368                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
369         })).Return(nil)
370
371         nodeb1 := &entities.NodebInfo{RanName: "test1", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
372         readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
373
374         nodeb1new := *nodeb1
375         nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
376         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test1_DISCONNECTED").Return(common.NewInternalError(fmt.Errorf("for tests")))
377
378         err := shutdownManager.Shutdown(e2tInstance1)
379
380         assert.NotNil(t, err)
381         readerMock.AssertExpectations(t)
382         writerMock.AssertExpectations(t)
383         httpClientMock.AssertExpectations(t)
384 }
385
386 func TestShutdownResourceNotFoundErrorInGetNodeb(t *testing.T) {
387         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
388
389         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
390         e2tInstance1.State = entities.Active
391         e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
392         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
393                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
394         })).Return(nil)
395
396         nodeb1 := &entities.NodebInfo{RanName: "test1", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
397         readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
398         var nodeb2 *entities.NodebInfo
399         readerMock.On("GetNodeb", "test2").Return(nodeb2, common.NewResourceNotFoundError("for testing"))
400
401         nodeb1new := *nodeb1
402         nodeb1new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
403         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test1_DISCONNECTED").Return(nil)
404
405         nodeb1NotAssociated := *nodeb1
406         nodeb1NotAssociated.AssociatedE2TInstanceAddress = ""
407         nodeb1NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
408         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
409
410         err := shutdownManager.Shutdown(e2tInstance1)
411
412         assert.NotNil(t, err)
413         readerMock.AssertExpectations(t)
414         writerMock.AssertExpectations(t)
415         httpClientMock.AssertExpectations(t)
416 }
417
418 func TestShutdownResourceGeneralErrorInGetNodeb(t *testing.T) {
419         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
420
421         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
422         e2tInstance1.State = entities.Active
423         e2tInstance1.AssociatedRanList = []string{"test1", "test2"}
424         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
425                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
426         })).Return(nil)
427
428         var nodeb1 *entities.NodebInfo
429         readerMock.On("GetNodeb", "test1").Return(nodeb1, common.NewInternalError(fmt.Errorf("for testing")))
430         nodeb2 := &entities.NodebInfo{RanName: "test2", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
431         readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
432
433         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, []string{"test1", "test2"}, nil)
434         marshaled, _ := json.Marshal(data)
435         body := bytes.NewBuffer(marshaled)
436         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
437         httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
438
439         writerMock.On("RemoveE2TInstance", E2TAddress).Return(nil)
440         readerMock.On("GetE2TAddresses").Return([]string{E2TAddress}, nil)
441         writerMock.On("SaveE2TAddresses", []string{}).Return(nil)
442
443         nodeb2new := *nodeb2
444         nodeb2new.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
445         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
446
447         nodeb2NotAssociated := *nodeb2
448         nodeb2NotAssociated.AssociatedE2TInstanceAddress = ""
449         nodeb2NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
450         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
451
452         err := shutdownManager.Shutdown(e2tInstance1)
453
454         assert.Nil(t, err)
455         readerMock.AssertExpectations(t)
456         writerMock.AssertExpectations(t)
457         httpClientMock.AssertExpectations(t)
458
459 }
460
461 func TestShutdownFailureInRemoveE2TInstance(t *testing.T) {
462         shutdownManager, readerMock, writerMock, httpClientMock := initE2TShutdownManagerTest(t)
463
464         e2tInstance1 := entities.NewE2TInstance(E2TAddress, PodName)
465         e2tInstance1.State = entities.Active
466         e2tInstance1.AssociatedRanList = []string{"test1", "test2", "test5"}
467         e2tInstance2 := entities.NewE2TInstance(E2TAddress2, PodName)
468         e2tInstance2.State = entities.Active
469         e2tInstance2.AssociatedRanList = []string{"test3"}
470         e2tInstance3 := entities.NewE2TInstance(E2TAddress3, PodName)
471         e2tInstance3.State = entities.Active
472         e2tInstance3.AssociatedRanList = []string{"test4"}
473         writerMock.On("SaveE2TInstance", mock.MatchedBy(func(e2tInstance *entities.E2TInstance) bool {
474                 return e2tInstance.Address == E2TAddress && e2tInstance.State == entities.ToBeDeleted
475         })).Return(nil)
476
477         nodeb1 := &entities.NodebInfo{RanName: "test1", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
478         readerMock.On("GetNodeb", "test1").Return(nodeb1, nil)
479         nodeb2 := &entities.NodebInfo{RanName: "test2", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
480         readerMock.On("GetNodeb", "test2").Return(nodeb2, nil)
481         nodeb5 := &entities.NodebInfo{RanName: "test5", AssociatedE2TInstanceAddress: E2TAddress, ConnectionStatus: entities.ConnectionStatus_CONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
482         readerMock.On("GetNodeb", "test5").Return(nodeb5, nil)
483
484         data := models.NewRoutingManagerDeleteRequestModel(E2TAddress, e2tInstance1.AssociatedRanList, nil)
485         marshaled, _ := json.Marshal(data)
486         body := bytes.NewBuffer(marshaled)
487         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
488         httpClientMock.On("Delete", "e2t", "application/json", body).Return(&http.Response{StatusCode: http.StatusCreated, Body: respBody}, nil)
489
490         writerMock.On("RemoveE2TInstance", E2TAddress).Return(common.NewInternalError(fmt.Errorf("for tests")))
491
492         /*** nodeb 1 connected ***/
493         nodeb1connected := *nodeb1
494         nodeb1connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
495         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test1_DISCONNECTED").Return(nil)
496
497         nodeb1NotAssociated := *nodeb1
498         nodeb1NotAssociated.AssociatedE2TInstanceAddress = ""
499         nodeb1NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
500         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
501
502         /*** nodeb 2 shutting down ***/
503         nodeb2connected := *nodeb2
504         nodeb2connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
505         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
506
507         nodeb2NotAssociated := *nodeb2
508         nodeb2NotAssociated.AssociatedE2TInstanceAddress = ""
509         nodeb2NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
510         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
511
512         /*** nodeb 5 connected ***/
513         nodeb5connected := *nodeb5
514         nodeb5connected.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
515         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, "test5_DISCONNECTED").Return(nil)
516
517         nodeb5NotAssociated := *nodeb5
518         nodeb5NotAssociated.AssociatedE2TInstanceAddress = ""
519         nodeb5NotAssociated.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
520         writerMock.On("UpdateNodebInfo", mock.Anything).Return(nil)
521
522         err := shutdownManager.Shutdown(e2tInstance1)
523
524         assert.IsType(t, &e2managererrors.RnibDbError{}, err)
525         readerMock.AssertExpectations(t)
526         writerMock.AssertExpectations(t)
527         httpClientMock.AssertExpectations(t)
528 }