[RICPLT-2165] Add rnibDataService to support retries
[ric-plt/e2mgr.git] / E2Manager / controllers / controller_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 package controllers
19
20 import (
21         "bytes"
22         "e2mgr/configuration"
23         "e2mgr/e2managererrors"
24         "e2mgr/e2pdus"
25         "e2mgr/logger"
26         "e2mgr/managers"
27         "e2mgr/mocks"
28         "e2mgr/models"
29         "e2mgr/providers/httpmsghandlerprovider"
30         "e2mgr/rNibWriter"
31         "e2mgr/rmrCgo"
32         "e2mgr/services"
33         "e2mgr/tests"
34         "encoding/json"
35         "fmt"
36         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
37         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
38         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
39         "github.com/gorilla/mux"
40         "github.com/stretchr/testify/assert"
41         "github.com/stretchr/testify/mock"
42         "io"
43         "io/ioutil"
44         "net/http"
45         "net/http/httptest"
46         "strings"
47         "testing"
48 )
49
50 func setupControllerTest(t *testing.T) (*Controller, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock){
51         log := initLog(t)
52         config := configuration.ParseConfiguration()
53
54         rmrMessengerMock := &mocks.RmrMessengerMock{}
55         readerMock := &mocks.RnibReaderMock{}
56         readerProvider := func() reader.RNibReader {
57                 return readerMock
58         }
59         writerMock := &mocks.RnibWriterMock{}
60         writerProvider := func() rNibWriter.RNibWriter {
61                 return writerMock
62         }
63         rnibDataService := services.NewRnibDataService(log, config, readerProvider, writerProvider)
64
65         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rnibDataService)
66         controller := NewController(log, getRmrService(rmrMessengerMock, log), rnibDataService, config, ranSetupManager)
67         return controller, readerMock, writerMock, rmrMessengerMock
68 }
69
70 func TestX2SetupInvalidBody(t *testing.T) {
71
72         controller, _, _, _ := setupControllerTest(t)
73
74         header := http.Header{}
75         header.Set("Content-Type", "application/json")
76         httpRequest, _ := http.NewRequest("POST", "http://localhost:3800/v1/nodeb/x2-setup", strings.NewReader("{}{}"))
77         httpRequest.Header = header
78
79         writer := httptest.NewRecorder()
80         controller.X2SetupHandler(writer, httpRequest)
81
82         var errorResponse = parseJsonRequest(t, writer.Body)
83
84         assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
85         assert.Equal(t, e2managererrors.NewInvalidJsonError().Code, errorResponse.Code)
86 }
87
88 func TestX2SetupSuccess(t *testing.T) {
89
90         controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
91
92         ranName := "test"
93         nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
94         readerMock.On("GetNodeb", ranName).Return(nb, nil)
95
96         var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
97         writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
98
99         payload := e2pdus.PackedX2setupRequest
100         xaction := []byte(ranName)
101         msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
102
103         rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
104
105         header := http.Header{}
106         header.Set("Content-Type", "application/json")
107         httpRequest := tests.GetHttpRequest()
108         httpRequest.Header = header
109
110         writer := httptest.NewRecorder()
111         controller.X2SetupHandler(writer, httpRequest)
112
113         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
114 }
115
116 func TestEndcSetupSuccess(t *testing.T) {
117
118         controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
119
120         ranName := "test"
121         nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
122         readerMock.On("GetNodeb", ranName).Return(nb, nil)
123
124         var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
125         writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
126
127         payload := e2pdus.PackedEndcX2setupRequest
128         xaction := []byte(ranName)
129         msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
130
131         rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
132
133         header := http.Header{}
134         header.Set("Content-Type", "application/json")
135         httpRequest := tests.GetHttpRequest()
136         httpRequest.Header = header
137
138         writer := httptest.NewRecorder()
139         controller.EndcSetupHandler(writer, httpRequest)
140
141         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
142 }
143
144 func TestShutdownHandlerRnibError(t *testing.T) {
145         controller, readerMock, _, _:= setupControllerTest(t)
146
147         rnibErr := &common.ResourceNotFoundError{}
148         var nbIdentityList []*entities.NbIdentity
149         readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr)
150
151         writer := httptest.NewRecorder()
152
153         controller.ShutdownHandler(writer, tests.GetHttpRequest())
154
155         var errorResponse = parseJsonRequest(t, writer.Body)
156
157         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
158         assert.Equal(t, errorResponse.Code, e2managererrors.NewRnibDbError().Code)
159 }
160
161 func TestHeaderValidationFailed(t *testing.T) {
162         controller, _, _, _ := setupControllerTest(t)
163
164         writer := httptest.NewRecorder()
165
166         header := &http.Header{}
167
168         controller.handleRequest(writer, header, httpmsghandlerprovider.ShutdownRequest, nil, true)
169
170         var errorResponse = parseJsonRequest(t, writer.Body)
171         err := e2managererrors.NewHeaderValidationError()
172
173         assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
174         assert.Equal(t, errorResponse.Code, err.Code)
175         assert.Equal(t, errorResponse.Message, err.Message)
176 }
177
178 func TestShutdownStatusNoContent(t *testing.T) {
179         controller, readerMock, _, _ := setupControllerTest(t)
180
181         var rnibError error
182         nbIdentityList := []*entities.NbIdentity{}
183         readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError)
184
185         writer := httptest.NewRecorder()
186         controller.ShutdownHandler(writer, tests.GetHttpRequest())
187
188         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
189 }
190
191 func TestHandleInternalError(t *testing.T) {
192         controller, _, _, _ := setupControllerTest(t)
193
194         writer := httptest.NewRecorder()
195         err := e2managererrors.NewInternalError()
196
197         controller.handleErrorResponse(err, writer)
198         var errorResponse = parseJsonRequest(t, writer.Body)
199
200         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
201         assert.Equal(t, errorResponse.Code, err.Code)
202         assert.Equal(t, errorResponse.Message, err.Message)
203 }
204
205 func TestHandleCommandAlreadyInProgressError(t *testing.T) {
206         controller, _, _, _ := setupControllerTest(t)
207         writer := httptest.NewRecorder()
208         err := e2managererrors.NewCommandAlreadyInProgressError()
209
210         controller.handleErrorResponse(err, writer)
211         var errorResponse = parseJsonRequest(t, writer.Body)
212
213         assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
214         assert.Equal(t, errorResponse.Code, err.Code)
215         assert.Equal(t, errorResponse.Message, err.Message)
216 }
217
218 func TestValidateHeaders(t *testing.T) {
219         controller, _, _, _ := setupControllerTest(t)
220
221         header := http.Header{}
222         header.Set("Content-Type", "application/json")
223         result := controller.validateRequestHeader(&header)
224
225         assert.Nil(t, result)
226 }
227
228 func parseJsonRequest(t *testing.T, r io.Reader) models.ErrorResponse {
229
230         var errorResponse models.ErrorResponse
231         body, err := ioutil.ReadAll(r)
232         if err != nil {
233                 t.Errorf("Error cannot deserialize json request")
234         }
235         json.Unmarshal(body, &errorResponse)
236
237         return errorResponse
238 }
239
240 func initLog(t *testing.T) *logger.Logger {
241         log, err := logger.InitLogger(logger.InfoLevel)
242         if err != nil {
243                 t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
244         }
245         return log
246 }
247
248 func TestX2ResetHandleSuccessfulRequestedCause(t *testing.T) {
249         controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
250
251         ranName := "test1"
252         payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
253         xaction := []byte(ranName)
254         msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
255         rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
256
257         writer := httptest.NewRecorder()
258
259         var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
260         readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
261
262         data4Req := map[string]interface{}{"cause": "protocol:transfer-syntax-error"}
263         b := new(bytes.Buffer)
264         _ = json.NewEncoder(b).Encode(data4Req)
265         req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
266         req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
267
268         controller.X2ResetHandler(writer, req)
269         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
270
271 }
272
273 func TestX2ResetHandleSuccessfulRequestedDefault(t *testing.T) {
274         controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
275
276         ranName := "test1"
277         // o&m intervention
278         payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
279         xaction := []byte(ranName)
280         msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
281         rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
282
283         writer := httptest.NewRecorder()
284
285         var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
286         readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
287
288         // no body
289         b := new(bytes.Buffer)
290         req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
291         req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
292
293         controller.X2ResetHandler(writer, req)
294         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
295
296 }
297
298 func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
299         controller, _, _, _ := setupControllerTest(t)
300
301         ranName := "test1"
302
303         writer := httptest.NewRecorder()
304
305         // Invalid json: attribute name without quotes (should be "cause":).
306         b := strings.NewReader("{cause:\"protocol:transfer-syntax-error\"")
307         req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
308         req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
309
310         controller.X2ResetHandler(writer, req)
311         assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
312
313 }
314
315 func TestHandleErrorResponse(t *testing.T) {
316         controller, _, _, _ := setupControllerTest(t)
317
318         writer := httptest.NewRecorder()
319         controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
320         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
321
322         writer = httptest.NewRecorder()
323         controller.handleErrorResponse(e2managererrors.NewCommandAlreadyInProgressError(), writer)
324         assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
325
326         writer = httptest.NewRecorder()
327         controller.handleErrorResponse(e2managererrors.NewHeaderValidationError(), writer)
328         assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
329
330         writer = httptest.NewRecorder()
331         controller.handleErrorResponse(e2managererrors.NewWrongStateError("", ""), writer)
332         assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
333
334         writer = httptest.NewRecorder()
335         controller.handleErrorResponse(e2managererrors.NewRequestValidationError(), writer)
336         assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
337
338         writer = httptest.NewRecorder()
339         controller.handleErrorResponse(e2managererrors.NewRmrError(), writer)
340         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
341
342         writer = httptest.NewRecorder()
343         controller.handleErrorResponse(e2managererrors.NewResourceNotFoundError(), writer)
344         assert.Equal(t, http.StatusNotFound, writer.Result().StatusCode)
345
346         writer = httptest.NewRecorder()
347         controller.handleErrorResponse(fmt.Errorf("ErrorError"), writer)
348         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
349 }