2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
23 "e2mgr/e2managererrors"
29 "e2mgr/providers/httpmsghandlerprovider"
32 "e2mgr/services/rmrsender"
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 "github.com/gorilla/mux"
39 "github.com/pkg/errors"
40 "github.com/stretchr/testify/assert"
41 "github.com/stretchr/testify/mock"
50 type controllerGetNodebTestContext struct {
52 nodebInfo *entities.NodebInfo
54 expectedStatusCode int
55 expectedJsonResponse string
58 type controllerGetNodebIdListTestContext struct {
59 nodebIdList []*entities.NbIdentity
61 expectedStatusCode int
62 expectedJsonResponse string
65 func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock) {
67 config := configuration.ParseConfiguration()
69 rmrMessengerMock := &mocks.RmrMessengerMock{}
70 readerMock := &mocks.RnibReaderMock{}
72 writerMock := &mocks.RnibWriterMock{}
74 rnibDataService := services.NewRnibDataService(log, config, readerMock, writerMock)
75 rmrSender := getRmrSender(rmrMessengerMock, log)
76 ranSetupManager := managers.NewRanSetupManager(log, rmrSender, rnibDataService)
77 e2tInstancesManager := managers.NewE2TInstancesManager(rnibDataService, log)
78 handlerProvider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(log, rmrSender, config, rnibDataService, ranSetupManager, e2tInstancesManager)
79 controller := NewNodebController(log, handlerProvider)
80 return controller, readerMock, writerMock, rmrMessengerMock
83 func TestX2SetupInvalidBody(t *testing.T) {
85 controller, _, _, _ := setupControllerTest(t)
87 header := http.Header{}
88 header.Set("Content-Type", "application/json")
89 httpRequest, _ := http.NewRequest("POST", "http://localhost:3800/v1/nodeb/x2-setup", strings.NewReader("{}{}"))
90 httpRequest.Header = header
92 writer := httptest.NewRecorder()
93 controller.X2Setup(writer, httpRequest)
95 var errorResponse = parseJsonRequest(t, writer.Body)
97 assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
98 assert.Equal(t, e2managererrors.NewInvalidJsonError().Code, errorResponse.Code)
101 //func TestX2SetupSuccess(t *testing.T) {
103 // controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
106 // nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST}
107 // readerMock.On("GetNodeb", ranName).Return(nb, nil)
109 // var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1}
110 // writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
112 // payload := e2pdus.PackedX2setupRequest
114 // msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction)
116 // rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
118 // header := http.Header{}
119 // header.Set("Content-Type", "application/json")
120 // httpRequest := tests.GetHttpRequest()
121 // httpRequest.Header = header
123 // writer := httptest.NewRecorder()
124 // controller.X2Setup(writer, httpRequest)
126 // assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
129 //func TestEndcSetupSuccess(t *testing.T) {
131 // controller, readerMock, writerMock, rmrMessengerMock := setupControllerTest(t)
134 // nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST}
135 // readerMock.On("GetNodeb", ranName).Return(nb, nil)
137 // var nbUpdated = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1}
138 // writerMock.On("UpdateNodebInfo", nbUpdated).Return(nil)
140 // payload := e2pdus.PackedEndcX2setupRequest
142 // msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction)
144 // rmrMessengerMock.On("SendMsg", mock.Anything).Return(msg, nil)
146 // header := http.Header{}
147 // header.Set("Content-Type", "application/json")
148 // httpRequest := tests.GetHttpRequest()
149 // httpRequest.Header = header
151 // writer := httptest.NewRecorder()
152 // controller.EndcSetup(writer, httpRequest)
154 // assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
157 func TestShutdownHandlerRnibError(t *testing.T) {
158 controller, readerMock, _, _ := setupControllerTest(t)
160 rnibErr := &common.ResourceNotFoundError{}
161 var nbIdentityList []*entities.NbIdentity
162 readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr)
164 writer := httptest.NewRecorder()
166 controller.Shutdown(writer, tests.GetHttpRequest())
168 var errorResponse = parseJsonRequest(t, writer.Body)
170 assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
171 assert.Equal(t, errorResponse.Code, e2managererrors.NewRnibDbError().Code)
174 func controllerGetNodebTestExecuter(t *testing.T, context *controllerGetNodebTestContext) {
175 controller, readerMock, _, _ := setupControllerTest(t)
176 writer := httptest.NewRecorder()
177 readerMock.On("GetNodeb", context.ranName).Return(context.nodebInfo, context.rnibError)
178 req, _ := http.NewRequest("GET", "/nodeb", nil)
179 req = mux.SetURLVars(req, map[string]string{"ranName": context.ranName})
180 controller.GetNodeb(writer, req)
181 assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode)
182 bodyBytes, _ := ioutil.ReadAll(writer.Body)
183 assert.Equal(t, context.expectedJsonResponse, string(bodyBytes))
186 func controllerGetNodebIdListTestExecuter(t *testing.T, context *controllerGetNodebIdListTestContext) {
187 controller, readerMock, _, _ := setupControllerTest(t)
188 writer := httptest.NewRecorder()
189 readerMock.On("GetListNodebIds").Return(context.nodebIdList, context.rnibError)
190 req, _ := http.NewRequest("GET", "/nodeb/ids", nil)
191 controller.GetNodebIdList(writer, req)
192 assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode)
193 bodyBytes, _ := ioutil.ReadAll(writer.Body)
194 assert.Equal(t, context.expectedJsonResponse, string(bodyBytes))
197 func TestControllerGetNodebSuccess(t *testing.T) {
200 context := controllerGetNodebTestContext{
202 nodebInfo: &entities.NodebInfo{RanName: ranName, Ip: "10.0.2.15", Port: 1234},
203 rnibError: rnibError,
204 expectedStatusCode: http.StatusOK,
205 expectedJsonResponse: fmt.Sprintf("{\"ranName\":\"%s\",\"ip\":\"10.0.2.15\",\"port\":1234}", ranName),
208 controllerGetNodebTestExecuter(t, &context)
211 func TestControllerGetNodebNotFound(t *testing.T) {
214 var nodebInfo *entities.NodebInfo
215 context := controllerGetNodebTestContext{
217 nodebInfo: nodebInfo,
218 rnibError: common.NewResourceNotFoundError("#reader.GetNodeb - Not found Error"),
219 expectedStatusCode: http.StatusNotFound,
220 expectedJsonResponse: "{\"errorCode\":404,\"errorMessage\":\"Resource not found\"}",
223 controllerGetNodebTestExecuter(t, &context)
226 func TestControllerGetNodebInternal(t *testing.T) {
228 var nodebInfo *entities.NodebInfo
229 context := controllerGetNodebTestContext{
231 nodebInfo: nodebInfo,
232 rnibError: common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")),
233 expectedStatusCode: http.StatusInternalServerError,
234 expectedJsonResponse: "{\"errorCode\":500,\"errorMessage\":\"RNIB error\"}",
237 controllerGetNodebTestExecuter(t, &context)
240 func TestControllerGetNodebIdListSuccess(t *testing.T) {
242 nodebIdList := []*entities.NbIdentity{
243 {InventoryName: "test1", GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId1", NbId: "nbId1"}},
244 {InventoryName: "test2", GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId2", NbId: "nbId2"}},
247 context := controllerGetNodebIdListTestContext{
248 nodebIdList: nodebIdList,
249 rnibError: rnibError,
250 expectedStatusCode: http.StatusOK,
251 expectedJsonResponse: "[{\"inventoryName\":\"test1\",\"globalNbId\":{\"plmnId\":\"plmnId1\",\"nbId\":\"nbId1\"}},{\"inventoryName\":\"test2\",\"globalNbId\":{\"plmnId\":\"plmnId2\",\"nbId\":\"nbId2\"}}]",
254 controllerGetNodebIdListTestExecuter(t, &context)
257 func TestControllerGetNodebIdListEmptySuccess(t *testing.T) {
259 nodebIdList := []*entities.NbIdentity{}
261 context := controllerGetNodebIdListTestContext{
262 nodebIdList: nodebIdList,
263 rnibError: rnibError,
264 expectedStatusCode: http.StatusOK,
265 expectedJsonResponse: "[]",
268 controllerGetNodebIdListTestExecuter(t, &context)
271 func TestControllerGetNodebIdListInternal(t *testing.T) {
272 var nodebIdList []*entities.NbIdentity
273 context := controllerGetNodebIdListTestContext{
274 nodebIdList: nodebIdList,
275 rnibError: common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")),
276 expectedStatusCode: http.StatusInternalServerError,
277 expectedJsonResponse: "{\"errorCode\":500,\"errorMessage\":\"RNIB error\"}",
280 controllerGetNodebIdListTestExecuter(t, &context)
283 func TestHeaderValidationFailed(t *testing.T) {
284 controller, _, _, _ := setupControllerTest(t)
286 writer := httptest.NewRecorder()
288 header := &http.Header{}
290 controller.handleRequest(writer, header, httpmsghandlerprovider.ShutdownRequest, nil, true)
292 var errorResponse = parseJsonRequest(t, writer.Body)
293 err := e2managererrors.NewHeaderValidationError()
295 assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
296 assert.Equal(t, errorResponse.Code, err.Code)
297 assert.Equal(t, errorResponse.Message, err.Message)
300 func TestShutdownStatusNoContent(t *testing.T) {
301 controller, readerMock, _, _ := setupControllerTest(t)
304 nbIdentityList := []*entities.NbIdentity{}
305 readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError)
307 writer := httptest.NewRecorder()
308 controller.Shutdown(writer, tests.GetHttpRequest())
310 assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
313 func TestHandleInternalError(t *testing.T) {
314 controller, _, _, _ := setupControllerTest(t)
316 writer := httptest.NewRecorder()
317 err := e2managererrors.NewInternalError()
319 controller.handleErrorResponse(err, writer)
320 var errorResponse = parseJsonRequest(t, writer.Body)
322 assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
323 assert.Equal(t, errorResponse.Code, err.Code)
324 assert.Equal(t, errorResponse.Message, err.Message)
327 func TestHandleCommandAlreadyInProgressError(t *testing.T) {
328 controller, _, _, _ := setupControllerTest(t)
329 writer := httptest.NewRecorder()
330 err := e2managererrors.NewCommandAlreadyInProgressError()
332 controller.handleErrorResponse(err, writer)
333 var errorResponse = parseJsonRequest(t, writer.Body)
335 assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
336 assert.Equal(t, errorResponse.Code, err.Code)
337 assert.Equal(t, errorResponse.Message, err.Message)
340 func TestValidateHeaders(t *testing.T) {
341 controller, _, _, _ := setupControllerTest(t)
343 header := http.Header{}
344 header.Set("Content-Type", "application/json")
345 result := controller.validateRequestHeader(&header)
347 assert.Nil(t, result)
350 func parseJsonRequest(t *testing.T, r io.Reader) models.ErrorResponse {
352 var errorResponse models.ErrorResponse
353 body, err := ioutil.ReadAll(r)
355 t.Errorf("Error cannot deserialize json request")
357 json.Unmarshal(body, &errorResponse)
362 func initLog(t *testing.T) *logger.Logger {
363 log, err := logger.InitLogger(logger.InfoLevel)
365 t.Errorf("#delete_all_request_handler_test.TestHandleSuccessFlow - failed to initialize logger, error: %s", err)
370 func TestX2ResetHandleSuccessfulRequestedCause(t *testing.T) {
371 controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
374 payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x40}
376 msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
377 rmrMessengerMock.On("SendMsg", msg, mock.Anything).Return(msg, nil)
379 writer := httptest.NewRecorder()
381 var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
382 readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
384 data4Req := map[string]interface{}{"cause": "protocol:transfer-syntax-error"}
385 b := new(bytes.Buffer)
386 _ = json.NewEncoder(b).Encode(data4Req)
387 req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
388 req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
390 controller.X2Reset(writer, req)
391 assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
395 func TestX2ResetHandleSuccessfulRequestedDefault(t *testing.T) {
396 controller, readerMock, _, rmrMessengerMock := setupControllerTest(t)
400 payload := []byte{0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x05, 0x40, 0x01, 0x64}
402 msg := rmrCgo.NewMBuf(rmrCgo.RIC_X2_RESET, len(payload), ranName, &payload, &xAction)
403 rmrMessengerMock.On("SendMsg", msg).Return(msg, nil)
405 writer := httptest.NewRecorder()
407 var nodeb = &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
408 readerMock.On("GetNodeb", ranName).Return(nodeb, nil)
411 b := new(bytes.Buffer)
412 req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
413 req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
415 controller.X2Reset(writer, req)
416 assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
420 func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
421 controller, _, _, _ := setupControllerTest(t)
425 writer := httptest.NewRecorder()
427 // Invalid json: attribute name without quotes (should be "cause":).
428 b := strings.NewReader("{cause:\"protocol:transfer-syntax-error\"")
429 req, _ := http.NewRequest("PUT", "https://localhost:3800/nodeb-reset", b)
430 req = mux.SetURLVars(req, map[string]string{"ranName": ranName})
432 controller.X2Reset(writer, req)
433 assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
437 func TestHandleErrorResponse(t *testing.T) {
438 controller, _, _, _ := setupControllerTest(t)
440 writer := httptest.NewRecorder()
441 controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
442 assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
444 writer = httptest.NewRecorder()
445 controller.handleErrorResponse(e2managererrors.NewCommandAlreadyInProgressError(), writer)
446 assert.Equal(t, http.StatusMethodNotAllowed, writer.Result().StatusCode)
448 writer = httptest.NewRecorder()
449 controller.handleErrorResponse(e2managererrors.NewHeaderValidationError(), writer)
450 assert.Equal(t, http.StatusUnsupportedMediaType, writer.Result().StatusCode)
452 writer = httptest.NewRecorder()
453 controller.handleErrorResponse(e2managererrors.NewWrongStateError("", ""), writer)
454 assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
456 writer = httptest.NewRecorder()
457 controller.handleErrorResponse(e2managererrors.NewRequestValidationError(), writer)
458 assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
460 writer = httptest.NewRecorder()
461 controller.handleErrorResponse(e2managererrors.NewRmrError(), writer)
462 assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
464 writer = httptest.NewRecorder()
465 controller.handleErrorResponse(e2managererrors.NewResourceNotFoundError(), writer)
466 assert.Equal(t, http.StatusNotFound, writer.Result().StatusCode)
468 writer = httptest.NewRecorder()
469 controller.handleErrorResponse(fmt.Errorf("ErrorError"), writer)
470 assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
473 func getRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
474 rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock)
475 rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
476 return rmrsender.NewRmrSender(log, rmrMessenger)