| // - |
| // ========================LICENSE_START================================= |
| // O-RAN-SC |
| // %% |
| // Copyright (C) 2022: Nordix Foundation |
| // %% |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // ========================LICENSE_END=================================== |
| // |
| package invokermanagement |
| |
| import ( |
| "fmt" |
| "net/http" |
| "os" |
| "testing" |
| |
| "oransc.org/nonrtric/sme/internal/invokermanagementapi" |
| |
| "github.com/labstack/echo/v4" |
| |
| "oransc.org/nonrtric/sme/internal/common29122" |
| "oransc.org/nonrtric/sme/internal/publishserviceapi" |
| |
| "oransc.org/nonrtric/sme/internal/publishservice" |
| publishmocks "oransc.org/nonrtric/sme/internal/publishservice/mocks" |
| |
| "github.com/deepmap/oapi-codegen/pkg/middleware" |
| "github.com/deepmap/oapi-codegen/pkg/testutil" |
| echomiddleware "github.com/labstack/echo/v4/middleware" |
| "github.com/stretchr/testify/assert" |
| "github.com/stretchr/testify/mock" |
| ) |
| |
| func TestOnboardInvoker(t *testing.T) { |
| var err error |
| apiId := "apiId" |
| aefId := "aefId" |
| apiRegisterMock := publishmocks.APIRegister{} |
| apiRegisterMock.On("AreAPIsRegistered", mock.Anything).Return(true) |
| invokerUnderTest, requestHandler := getEcho(&apiRegisterMock) |
| |
| description := "description" |
| domainName := "domain" |
| var protocol publishserviceapi.Protocol = "HTTP_1_1" |
| var apiList invokermanagementapi.APIList = []publishserviceapi.ServiceAPIDescription{ |
| { |
| ApiId: &apiId, |
| ApiName: "api", |
| Description: &description, |
| AefProfiles: &[]publishserviceapi.AefProfile{ |
| { |
| AefId: aefId, |
| DomainName: &domainName, |
| Protocol: &protocol, |
| Versions: []publishserviceapi.Version{ |
| { |
| ApiVersion: "v1", |
| Resources: &[]publishserviceapi.Resource{ |
| { |
| ResourceName: "app", |
| CommType: "REQUEST_RESPONSE", |
| Uri: "uri", |
| Operations: &[]publishserviceapi.Operation{ |
| "POST", |
| }, |
| }, |
| }, |
| }, |
| }, |
| }, |
| }, |
| }, |
| } |
| invokerInfo := "invoker a" |
| newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ |
| ApiInvokerInformation: &invokerInfo, |
| NotificationDestination: "url", |
| OnboardingInformation: invokermanagementapi.OnboardingInformation{ |
| ApiInvokerPublicKey: "key", |
| }, |
| ApiList: &apiList, |
| } |
| |
| // Onboard a valid invoker |
| result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusCreated, result.Code()) |
| var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails |
| err = result.UnmarshalBodyToObject(&resultInvoker) |
| assert.NoError(t, err, "error unmarshaling response") |
| assert.Equal(t, "api_invoker_id_invoker_a", *resultInvoker.ApiInvokerId) |
| assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination) |
| assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey) |
| assert.Equal(t, "onboarding_secret_invoker_a", *resultInvoker.OnboardingInformation.OnboardingSecret) |
| assert.Equal(t, "http://example.com/onboardedInvokers/"+*resultInvoker.ApiInvokerId, result.Recorder.Header().Get(echo.HeaderLocation)) |
| assert.True(t, invokerUnderTest.IsInvokerRegistered("api_invoker_id_invoker_a")) |
| assert.True(t, invokerUnderTest.VerifyInvokerSecret("api_invoker_id_invoker_a", "onboarding_secret_invoker_a")) |
| apiRegisterMock.AssertCalled(t, "AreAPIsRegistered", mock.Anything) |
| |
| // Onboard an invoker missing required NotificationDestination, should get 400 with problem details |
| invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ |
| OnboardingInformation: invokermanagementapi.OnboardingInformation{ |
| ApiInvokerPublicKey: "key", |
| }, |
| } |
| result = testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(invalidInvoker).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusBadRequest, result.Code()) |
| var problemDetails common29122.ProblemDetails |
| err = result.UnmarshalBodyToObject(&problemDetails) |
| assert.NoError(t, err, "error unmarshaling response") |
| badRequest := 400 |
| assert.Equal(t, &badRequest, problemDetails.Status) |
| errMsg := "Invoker missing required NotificationDestination" |
| assert.Equal(t, &errMsg, problemDetails.Cause) |
| |
| // Onboard an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details |
| invalidInvoker = invokermanagementapi.APIInvokerEnrolmentDetails{ |
| NotificationDestination: "url", |
| } |
| |
| result = testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(invalidInvoker).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusBadRequest, result.Code()) |
| err = result.UnmarshalBodyToObject(&problemDetails) |
| assert.NoError(t, err, "error unmarshaling response") |
| assert.Equal(t, &badRequest, problemDetails.Status) |
| errMsg = "Invoker missing required OnboardingInformation.ApiInvokerPublicKey" |
| assert.Equal(t, &errMsg, problemDetails.Cause) |
| } |
| |
| func TestDeleteInvoker(t *testing.T) { |
| _, requestHandler := getEcho(nil) |
| |
| newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ |
| NotificationDestination: "url", |
| OnboardingInformation: invokermanagementapi.OnboardingInformation{ |
| ApiInvokerPublicKey: "key", |
| }, |
| } |
| |
| // Onboard an invoker |
| result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler) |
| var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails |
| result.UnmarshalBodyToObject(&resultInvoker) |
| |
| invokerUrl := result.Recorder.Header().Get(echo.HeaderLocation) |
| |
| // Delete the invoker |
| result = testutil.NewRequest().Delete(invokerUrl).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusNoContent, result.Code()) |
| } |
| |
| func TestUpdateInvoker(t *testing.T) { |
| _, requestHandler := getEcho(nil) |
| |
| newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ |
| NotificationDestination: "url", |
| OnboardingInformation: invokermanagementapi.OnboardingInformation{ |
| ApiInvokerPublicKey: "key", |
| }, |
| } |
| |
| // Onboard an invoker |
| result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler) |
| var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails |
| result.UnmarshalBodyToObject(&resultInvoker) |
| |
| invokerId := resultInvoker.ApiInvokerId |
| invokerUrl := result.Recorder.Header().Get(echo.HeaderLocation) |
| |
| // Update the invoker with valid invoker, should return 200 with invoker details |
| result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(resultInvoker).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusOK, result.Code()) |
| err := result.UnmarshalBodyToObject(&resultInvoker) |
| assert.NoError(t, err, "error unmarshaling response") |
| assert.Equal(t, invokerId, resultInvoker.ApiInvokerId) |
| assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination) |
| assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey) |
| |
| // Update with an invoker missing required NotificationDestination, should get 400 with problem details |
| validOnboardingInfo := invokermanagementapi.OnboardingInformation{ |
| ApiInvokerPublicKey: "key", |
| } |
| invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ |
| ApiInvokerId: invokerId, |
| OnboardingInformation: validOnboardingInfo, |
| } |
| result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusBadRequest, result.Code()) |
| var problemDetails common29122.ProblemDetails |
| err = result.UnmarshalBodyToObject(&problemDetails) |
| assert.NoError(t, err, "error unmarshaling response") |
| badRequest := 400 |
| assert.Equal(t, &badRequest, problemDetails.Status) |
| errMsg := "Invoker missing required NotificationDestination" |
| assert.Equal(t, &errMsg, problemDetails.Cause) |
| |
| // Update with an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details |
| invalidInvoker.NotificationDestination = "url" |
| invalidInvoker.OnboardingInformation = invokermanagementapi.OnboardingInformation{} |
| result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusBadRequest, result.Code()) |
| err = result.UnmarshalBodyToObject(&problemDetails) |
| assert.NoError(t, err, "error unmarshaling response") |
| assert.Equal(t, &badRequest, problemDetails.Status) |
| errMsg = "Invoker missing required OnboardingInformation.ApiInvokerPublicKey" |
| assert.Equal(t, &errMsg, problemDetails.Cause) |
| |
| // Update with an invoker with other ApiInvokerId than the one provided in the URL, should get 400 with problem details |
| invalidId := "1" |
| invalidInvoker.ApiInvokerId = &invalidId |
| invalidInvoker.OnboardingInformation = validOnboardingInfo |
| result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusBadRequest, result.Code()) |
| err = result.UnmarshalBodyToObject(&problemDetails) |
| assert.NoError(t, err, "error unmarshaling response") |
| assert.Equal(t, &badRequest, problemDetails.Status) |
| errMsg = "Invoker ApiInvokerId not matching" |
| assert.Equal(t, &errMsg, problemDetails.Cause) |
| |
| // Update an invoker that has not been onboarded, shold get 404 with problem details |
| missingId := "1" |
| newInvoker.ApiInvokerId = &missingId |
| result = testutil.NewRequest().Put("/onboardedInvokers/"+missingId).WithJsonBody(newInvoker).Go(t, requestHandler) |
| |
| assert.Equal(t, http.StatusNotFound, result.Code()) |
| err = result.UnmarshalBodyToObject(&problemDetails) |
| assert.NoError(t, err, "error unmarshaling response") |
| notFound := 404 |
| assert.Equal(t, ¬Found, problemDetails.Status) |
| errMsg = "The invoker to update has not been onboarded" |
| assert.Equal(t, &errMsg, problemDetails.Cause) |
| |
| } |
| |
| func getEcho(apiRegister publishservice.APIRegister) (*InvokerManager, *echo.Echo) { |
| swagger, err := invokermanagementapi.GetSwagger() |
| if err != nil { |
| fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err) |
| os.Exit(1) |
| } |
| |
| swagger.Servers = nil |
| |
| im := NewInvokerManager(apiRegister) |
| |
| e := echo.New() |
| e.Use(echomiddleware.Logger()) |
| e.Use(middleware.OapiRequestValidator(swagger)) |
| |
| invokermanagementapi.RegisterHandlers(e, im) |
| return im, e |
| } |