[RICPLT-2048] X2 ENDC Setup request refactoring - unit test added
[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/tests"
33         "encoding/json"
34         "fmt"
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         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
38         "github.com/gorilla/mux"
39         "github.com/stretchr/testify/assert"
40         "github.com/stretchr/testify/mock"
41         "io"
42         "io/ioutil"
43         "net/http"
44         "net/http/httptest"
45         "strings"
46         "testing"
47 )
48
49 func TestX2SetupInvalidBody(t *testing.T) {
50
51         readerMock, writerMock, rmrMessengerMock, ranSetupManager := initTest(t)
52         log := initLog(t)
53
54         readerProvider := func() reader.RNibReader {
55                 return readerMock
56         }
57         writerProvider := func() rNibWriter.RNibWriter {
58                 return writerMock
59         }
60
61         header := http.Header{}
62         header.Set("Content-Type", "application/json")
63         httpRequest, _ := http.NewRequest("POST", "http://localhost:3800/v1/nodeb/x2-setup", strings.NewReader("{}{}"))
64         httpRequest.Header = header
65
66         writer := httptest.NewRecorder()
67         config := configuration.ParseConfiguration()
68         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
69         controller.X2SetupHandler(writer, httpRequest)
70
71         var errorResponse = parseJsonRequest(t, writer.Body)
72
73         assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
74         assert.Equal(t, e2managererrors.NewInvalidJsonError().Code, errorResponse.Code)
75 }
76
77 func TestX2SetupSuccess(t *testing.T) {
78
79         readerMock, writerMock, rmrMessengerMock, ranSetupManager := initTest(t)
80         log := initLog(t)
81
82         readerProvider := func() reader.RNibReader {
83                 return readerMock
84         }
85         writerProvider := func() rNibWriter.RNibWriter {
86                 return writerMock
87         }
88
89         ranName := "test"
90         nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
91         readerMock.On("GetNodeb", ranName).Return(nb, nil)
92
93         var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
94         writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
95
96         payload := e2pdus.PackedX2setupRequest
97         xaction := []byte(ranName)
98         msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
99
100         rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
101
102         header := http.Header{}
103         header.Set("Content-Type", "application/json")
104         httpRequest := tests.GetHttpRequest()
105         httpRequest.Header = header
106
107         writer := httptest.NewRecorder()
108         config := configuration.ParseConfiguration()
109         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
110         controller.X2SetupHandler(writer, httpRequest)
111
112         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
113 }
114
115 func TestEndcSetupSuccess(t *testing.T) {
116
117         readerMock, writerMock, rmrMessengerMock, ranSetupManager := initTest(t)
118         log := initLog(t)
119
120         readerProvider := func() reader.RNibReader {
121                 return readerMock
122         }
123         writerProvider := func() rNibWriter.RNibWriter {
124                 return writerMock
125         }
126
127         ranName := "test"
128         nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
129         readerMock.On("GetNodeb", ranName).Return(nb, nil)
130
131         var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
132         writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
133
134         payload := e2pdus.PackedEndcX2setupRequest
135         xaction := []byte(ranName)
136         msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xaction)
137
138         rmrMessengerMock.On("SendMsg", mock.Anything, mock.Anything).Return(msg, nil)
139
140         header := http.Header{}
141         header.Set("Content-Type", "application/json")
142         httpRequest := tests.GetHttpRequest()
143         httpRequest.Header = header
144
145         writer := httptest.NewRecorder()
146         config := configuration.ParseConfiguration()
147         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
148         controller.EndcSetupHandler(writer, httpRequest)
149
150         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
151 }
152
153 func TestShutdownHandlerRnibError(t *testing.T) {
154         log := initLog(t)
155         config := configuration.ParseConfiguration()
156
157         rmrMessengerMock := &mocks.RmrMessengerMock{}
158         readerMock := &mocks.RnibReaderMock{}
159         readerProvider := func() reader.RNibReader {
160                 return readerMock
161         }
162         writerMock := &mocks.RnibWriterMock{}
163         writerProvider := func() rNibWriter.RNibWriter {
164                 return writerMock
165         }
166
167         rnibErr := &common.ResourceNotFoundError{}
168         var nbIdentityList []*entities.NbIdentity
169         readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr)
170
171         writer := httptest.NewRecorder()
172         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
173         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
174         controller.ShutdownHandler(writer, tests.GetHttpRequest())
175
176         var errorResponse = parseJsonRequest(t, writer.Body)
177
178         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
179         assert.Equal(t, errorResponse.Code, e2managererrors.NewRnibDbError().Code)
180 }
181
182 func TestHeaderValidationFailed(t *testing.T) {
183         log := initLog(t)
184         config := configuration.ParseConfiguration()
185
186         rmrMessengerMock := &mocks.RmrMessengerMock{}
187         readerMock := &mocks.RnibReaderMock{}
188         readerProvider := func() reader.RNibReader {
189                 return readerMock
190         }
191         writerMock := &mocks.RnibWriterMock{}
192         writerProvider := func() rNibWriter.RNibWriter {
193                 return writerMock
194         }
195
196         writer := httptest.NewRecorder()
197         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
198         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
199
200         header := &http.Header{}
201
202         controller.handleRequest(writer, header, httpmsghandlerprovider.ShutdownRequest, nil, true)
203
204         var errorResponse = parseJsonRequest(t, writer.Body)
205         err := e2managererrors.NewHeaderValidationError()
206
207         assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
208         assert.Equal(t, errorResponse.Code, err.Code)
209         assert.Equal(t, errorResponse.Message, err.Message)
210 }
211
212 func TestShutdownStatusNoContent(t *testing.T) {
213         log := initLog(t)
214
215         rmrMessengerMock := &mocks.RmrMessengerMock{}
216         readerMock := &mocks.RnibReaderMock{}
217         readerProvider := func() reader.RNibReader {
218                 return readerMock
219         }
220         writerMock := &mocks.RnibWriterMock{}
221         writerProvider := func() rNibWriter.RNibWriter {
222                 return writerMock
223         }
224         config := configuration.ParseConfiguration()
225
226         var rnibError error
227         nbIdentityList := []*entities.NbIdentity{}
228         readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError)
229
230         writer := httptest.NewRecorder()
231         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
232         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
233         controller.ShutdownHandler(writer, tests.GetHttpRequest())
234
235         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
236 }
237
238 func TestHandleInternalError(t *testing.T) {
239         log := initLog(t)
240         config := configuration.ParseConfiguration()
241
242         rmrMessengerMock := &mocks.RmrMessengerMock{}
243         readerMock := &mocks.RnibReaderMock{}
244         readerProvider := func() reader.RNibReader {
245                 return readerMock
246         }
247         writerMock := &mocks.RnibWriterMock{}
248         writerProvider := func() rNibWriter.RNibWriter {
249                 return writerMock
250         }
251
252         writer := httptest.NewRecorder()
253         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
254         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
255         err := e2managererrors.NewInternalError()
256
257         controller.handleErrorResponse(err, writer)
258         var errorResponse = parseJsonRequest(t, writer.Body)
259
260         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
261         assert.Equal(t, errorResponse.Code, err.Code)
262         assert.Equal(t, errorResponse.Message, err.Message)
263 }
264
265 func TestHandleCommandAlreadyInProgressError(t *testing.T) {
266         log := initLog(t)
267         config := configuration.ParseConfiguration()
268
269         rmrMessengerMock := &mocks.RmrMessengerMock{}
270         readerMock := &mocks.RnibReaderMock{}
271         readerProvider := func() reader.RNibReader {
272                 return readerMock
273         }
274         writerMock := &mocks.RnibWriterMock{}
275         writerProvider := func() rNibWriter.RNibWriter {
276                 return writerMock
277         }
278         writer := httptest.NewRecorder()
279         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
280         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
281         err := e2managererrors.NewCommandAlreadyInProgressError()
282
283         controller.handleErrorResponse(err, writer)
284         var errorResponse = parseJsonRequest(t, writer.Body)
285
286         assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
287         assert.Equal(t, errorResponse.Code, err.Code)
288         assert.Equal(t, errorResponse.Message, err.Message)
289 }
290
291 func TestValidateHeaders(t *testing.T) {
292         log := initLog(t)
293
294         rmrMessengerMock := &mocks.RmrMessengerMock{}
295         readerMock := &mocks.RnibReaderMock{}
296         readerProvider := func() reader.RNibReader {
297                 return readerMock
298         }
299         writerMock := &mocks.RnibWriterMock{}
300         writerProvider := func() rNibWriter.RNibWriter {
301                 return writerMock
302         }
303         config := configuration.ParseConfiguration()
304         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
305         controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, ranSetupManager)
306
307         header := http.Header{}
308         header.Set("Content-Type", "application/json")
309         result := controller.validateRequestHeader(&header)
310
311         assert.Nil(t, result)
312 }
313
314 func parseJsonRequest(t *testing.T, r io.Reader) models.ErrorResponse {
315
316         var errorResponse models.ErrorResponse
317         body, err := ioutil.ReadAll(r)
318         if err != nil {
319                 t.Errorf("Error cannot deserialize json request")
320         }
321         json.Unmarshal(body, &errorResponse)
322
323         return errorResponse
324 }
325
326 func initLog(t *testing.T) *logger.Logger {
327         log, err := logger.InitLogger(logger.InfoLevel)
328         if err != nil {
329                 t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
330         }
331         return log
332 }
333
334 func TestX2ResetHandleSuccessfulRequestedCause(t *testing.T) {
335         log := initLog(t)
336
337         ranName := "test1"
338
339         readerMock := &mocks.RnibReaderMock{}
340         readerProvider := func() reader.RNibReader {
341                 return readerMock
342         }
343         writerMock := &mocks.RnibWriterMock{}
344         writerProvider := func() rNibWriter.RNibWriter {
345                 return writerMock
346         }
347         payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
348         xaction := []byte(ranName)
349         msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
350         rmrMessengerMock := &mocks.RmrMessengerMock{}
351         rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
352
353         config := configuration.ParseConfiguration()
354         rmrService := getRmrService(rmrMessengerMock, log)
355
356         writer := httptest.NewRecorder()
357         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
358         controller := NewController(log, rmrService, readerProvider, writerProvider, config, ranSetupManager)
359
360         var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
361         readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
362
363         data4Req := map[string]interface{}{"cause": "protocol:transfer-syntax-error"}
364         b := new(bytes.Buffer)
365         _ = json.NewEncoder(b).Encode(data4Req)
366         req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
367         req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
368
369         controller.X2ResetHandler(writer, req)
370         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
371
372 }
373
374 func TestX2ResetHandleSuccessfulRequestedDefault(t *testing.T) {
375         log := initLog(t)
376
377         ranName := "test1"
378
379         readerMock := &mocks.RnibReaderMock{}
380         readerProvider := func() reader.RNibReader {
381                 return readerMock
382         }
383         writerMock := &mocks.RnibWriterMock{}
384         writerProvider := func() rNibWriter.RNibWriter {
385                 return writerMock
386         }
387         // o&m intervention
388         payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
389         xaction := []byte(ranName)
390         msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xaction)
391         rmrMessengerMock := &mocks.RmrMessengerMock{}
392         rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
393
394         config := configuration.ParseConfiguration()
395         rmrService := getRmrService(rmrMessengerMock, log)
396
397         writer := httptest.NewRecorder()
398         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
399         controller := NewController(log, rmrService, readerProvider, writerProvider, config, ranSetupManager)
400
401         var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
402         readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
403
404         // no body
405         b := new(bytes.Buffer)
406         req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
407         req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
408
409         controller.X2ResetHandler(writer, req)
410         assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
411
412 }
413
414 func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
415         log := initLog(t)
416
417         ranName := "test1"
418
419         readerMock := &mocks.RnibReaderMock{}
420         readerProvider := func() reader.RNibReader {
421                 return readerMock
422         }
423         writerMock := &mocks.RnibWriterMock{}
424         writerProvider := func() rNibWriter.RNibWriter {
425                 return writerMock
426         }
427         rmrMessengerMock := &mocks.RmrMessengerMock{}
428
429         config := configuration.ParseConfiguration()
430         rmrService := getRmrService(rmrMessengerMock, log)
431
432         writer := httptest.NewRecorder()
433         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
434         controller := NewController(log, rmrService, readerProvider, writerProvider, config, ranSetupManager)
435
436         // Invalid json: attribute name without quotes (should be "cause":).
437         b := strings.NewReader("{cause:\"protocol:transfer-syntax-error\"")
438         req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
439         req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
440
441         controller.X2ResetHandler(writer, req)
442         assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
443
444 }
445
446 func TestHandleErrorResponse(t *testing.T) {
447         log := initLog(t)
448
449         readerMock := &mocks.RnibReaderMock{}
450         readerProvider := func() reader.RNibReader {
451                 return readerMock
452         }
453         writerMock := &mocks.RnibWriterMock{}
454         writerProvider := func() rNibWriter.RNibWriter {
455                 return writerMock
456         }
457         rmrMessengerMock := &mocks.RmrMessengerMock{}
458
459         config := configuration.ParseConfiguration()
460         rmrService := getRmrService(rmrMessengerMock, log)
461         ranSetupManager := managers.NewRanSetupManager(log, getRmrService(rmrMessengerMock, log), rNibWriter.GetRNibWriter)
462         controller := NewController(log, rmrService, readerProvider, writerProvider, config, ranSetupManager)
463
464         writer := httptest.NewRecorder()
465         controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
466         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
467
468         writer = httptest.NewRecorder()
469         controller.handleErrorResponse(e2managererrors.NewCommandAlreadyInProgressError(), writer)
470         assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
471
472         writer = httptest.NewRecorder()
473         controller.handleErrorResponse(e2managererrors.NewHeaderValidationError(), writer)
474         assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
475
476         writer = httptest.NewRecorder()
477         controller.handleErrorResponse(e2managererrors.NewWrongStateError("", ""), writer)
478         assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
479
480         writer = httptest.NewRecorder()
481         controller.handleErrorResponse(e2managererrors.NewRequestValidationError(), writer)
482         assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
483
484         writer = httptest.NewRecorder()
485         controller.handleErrorResponse(e2managererrors.NewRmrError(), writer)
486         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
487
488         writer = httptest.NewRecorder()
489         controller.handleErrorResponse(e2managererrors.NewResourceNotFoundError(), writer)
490         assert.Equal(t, http.StatusNotFound, writer.Result().StatusCode)
491
492         writer = httptest.NewRecorder()
493         controller.handleErrorResponse(fmt.Errorf("ErrorError"), writer)
494         assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
495 }
496
497 func initTest(t *testing.T)(*mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *managers.RanSetupManager) {
498         log := initLog(t)
499
500         readerMock := &mocks.RnibReaderMock{}
501         writerMock := &mocks.RnibWriterMock{}
502         writerProvider := func() rNibWriter.RNibWriter {
503                 return writerMock
504         }
505
506         rmrMessengerMock := &mocks.RmrMessengerMock{}
507         rmrService := getRmrService(rmrMessengerMock, log)
508
509         ranSetupManager := managers.NewRanSetupManager(log, rmrService, writerProvider)
510
511         return readerMock, writerMock, rmrMessengerMock, ranSetupManager
512 }