blob: 0b7b924570cca371410c6a11d122389e435b1f61 [file] [log] [blame]
// -
// ========================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, &notFound, 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
}