RIC-11565:Add support for Multiple E2 Nodes: CU/DU for the case having same GNBId
[ric-plt/e2mgr.git] / E2Manager / handlers / rmrmsghandlers / ran_lost_connection_handler_test.go
1 //// Copyright 2019 AT&T Intellectual Property
2 //// Copyright 2019 Nokia
3 ////
4 //// Licensed under the Apache License, Version 2.0 (the "License");
5 //// you may not use this file except in compliance with the License.
6 //// You may obtain a copy of the License at
7 ////
8 ////      http://www.apache.org/licenses/LICENSE-2.0
9 ////
10 //// Unless required by applicable law or agreed to in writing, software
11 //// distributed under the License is distributed on an "AS IS" BASIS,
12 //// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 //// See the License for the specific language governing permissions and
14 //// limitations under the License.
15
16 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
17 //  platform project (RICP).
18
19 package rmrmsghandlers
20
21 import (
22         "bytes"
23         "e2mgr/clients"
24         "e2mgr/configuration"
25         "e2mgr/logger"
26         "e2mgr/managers"
27         "e2mgr/mocks"
28         "e2mgr/models"
29         "e2mgr/services"
30         "encoding/json"
31         "io/ioutil"
32         "net/http"
33         "testing"
34
35         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
36         "github.com/stretchr/testify/mock"
37 )
38
39 const (
40         ranName    = "test"
41         e2tAddress = "10.10.2.15:9800"
42 )
43
44 func setupLostConnectionHandlerTest(isSuccessfulHttpPost bool) (*RanLostConnectionHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.HttpClientMock) {
45         InfoLevel := int8(3)
46         logger, _ := logger.InitLogger(InfoLevel)
47         config := &configuration.Configuration{
48                 RnibRetryIntervalMs:       10,
49                 MaxRnibConnectionAttempts: 3,
50                 RnibWriter: configuration.RnibWriterConfig{
51                         StateChangeMessageChannel: StateChangeMessageChannel,
52                 },
53         }
54
55         readerMock := &mocks.RnibReaderMock{}
56         writerMock := &mocks.RnibWriterMock{}
57         rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock)
58         e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, logger)
59         httpClientMock := &mocks.HttpClientMock{}
60         routingManagerClient := clients.NewRoutingManagerClient(logger, config, httpClientMock)
61         ranListManager := managers.NewRanListManager(logger, rnibDataService)
62         ranAlarmService := services.NewRanAlarmService(logger, config)
63         ranConnectStatusChangeManager := managers.NewRanConnectStatusChangeManager(logger, rnibDataService, ranListManager, ranAlarmService)
64
65         e2tAssociationManager := managers.NewE2TAssociationManager(logger, rnibDataService, e2tInstancesManager, routingManagerClient, ranConnectStatusChangeManager)
66         ranDisconnectionManager := managers.NewRanDisconnectionManager(logger, configuration.ParseConfiguration(), rnibDataService, e2tAssociationManager, ranConnectStatusChangeManager)
67         handler := NewRanLostConnectionHandler(logger, ranDisconnectionManager)
68
69         return handler, readerMock, writerMock, httpClientMock
70 }
71
72 func mockHttpClient(httpClientMock *mocks.HttpClientMock, isSuccessful bool) {
73         data := models.RoutingManagerE2TDataList{models.NewRoutingManagerE2TData(e2tAddress, RanName)}
74         marshaled, _ := json.Marshal(data)
75         body := bytes.NewBuffer(marshaled)
76         respBody := ioutil.NopCloser(bytes.NewBufferString(""))
77         var respStatusCode int
78         if isSuccessful {
79                 respStatusCode = http.StatusCreated
80         } else {
81                 respStatusCode = http.StatusBadRequest
82         }
83         httpClientMock.On("Post", clients.DissociateRanE2TInstanceApiSuffix, "application/json", body).Return(&http.Response{StatusCode: respStatusCode, Body: respBody}, nil)
84 }
85
86 func TestLostConnectionHandlerConnectingRanSuccess(t *testing.T) {
87         handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTest(true)
88
89         origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: e2tAddress}
90         var rnibErr error
91         readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
92         updatedNodebInfo1 := *origNodebInfo
93         updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
94         writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr)
95         updatedNodebInfo2 := *origNodebInfo
96         updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
97         updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
98         writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr)
99         e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList: []string{ranName}}
100         readerMock.On("GetE2TInstance", e2tAddress).Return(e2tInstance, nil)
101         e2tInstanceToSave := *e2tInstance
102         e2tInstanceToSave.AssociatedRanList = []string{}
103         writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
104         mockHttpClient(httpClientMock, true)
105         notificationRequest := models.NotificationRequest{RanName: ranName}
106         handler.Handle(&notificationRequest)
107         readerMock.AssertExpectations(t)
108         writerMock.AssertExpectations(t)
109         httpClientMock.AssertExpectations(t)
110         writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
111 }
112
113 func TestLostConnectionHandlerConnectedRanSuccess(t *testing.T) {
114         handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTest(true)
115
116         origNodebInfo := &entities.NodebInfo{
117                 RanName:                      ranName,
118                 GlobalNbId:                   &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"},
119                 ConnectionStatus:             entities.ConnectionStatus_CONNECTED,
120                 AssociatedE2TInstanceAddress: e2tAddress,
121         }
122         var rnibErr error
123         readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
124         updatedNodebInfo1 := *origNodebInfo
125         updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
126         writerMock.On("UpdateNodebInfoOnConnectionStatusInversion", mock.Anything, ranName+"_DISCONNECTED").Return(rnibErr)
127         updatedNodebInfo2 := *origNodebInfo
128         updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
129         updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
130         writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr)
131         e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList: []string{ranName}}
132         readerMock.On("GetE2TInstance", e2tAddress).Return(e2tInstance, nil)
133         e2tInstanceToSave := *e2tInstance
134         e2tInstanceToSave.AssociatedRanList = []string{}
135         writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
136         mockHttpClient(httpClientMock, true)
137         notificationRequest := models.NotificationRequest{RanName: ranName}
138         handler.Handle(&notificationRequest)
139         readerMock.AssertExpectations(t)
140         writerMock.AssertExpectations(t)
141         httpClientMock.AssertExpectations(t)
142         writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 1)
143 }
144
145 func TestLostConnectionHandlerRmDissociateFailure(t *testing.T) {
146         handler, readerMock, writerMock, httpClientMock := setupLostConnectionHandlerTest(false)
147
148         origNodebInfo := &entities.NodebInfo{RanName: ranName, GlobalNbId: &entities.GlobalNbId{PlmnId: "xxx", NbId: "yyy"}, ConnectionStatus: entities.ConnectionStatus_CONNECTING, AssociatedE2TInstanceAddress: e2tAddress}
149         var rnibErr error
150         readerMock.On("GetNodeb", ranName).Return(origNodebInfo, rnibErr)
151         updatedNodebInfo1 := *origNodebInfo
152         updatedNodebInfo1.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
153         writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr)
154         updatedNodebInfo2 := *origNodebInfo
155         updatedNodebInfo2.ConnectionStatus = entities.ConnectionStatus_DISCONNECTED
156         updatedNodebInfo2.AssociatedE2TInstanceAddress = ""
157         writerMock.On("UpdateNodebInfo", mock.Anything).Return(rnibErr)
158         e2tInstance := &entities.E2TInstance{Address: e2tAddress, AssociatedRanList: []string{ranName}}
159         readerMock.On("GetE2TInstance", e2tAddress).Return(e2tInstance, nil)
160         e2tInstanceToSave := *e2tInstance
161         e2tInstanceToSave.AssociatedRanList = []string{}
162         writerMock.On("SaveE2TInstance", &e2tInstanceToSave).Return(nil)
163         mockHttpClient(httpClientMock, false)
164         notificationRequest := models.NotificationRequest{RanName: ranName}
165         handler.Handle(&notificationRequest)
166         readerMock.AssertExpectations(t)
167         writerMock.AssertExpectations(t)
168         httpClientMock.AssertExpectations(t)
169         writerMock.AssertNumberOfCalls(t, "UpdateNodebInfo", 2)
170 }