X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=capifcore%2Finternal%2Finvokermanagement%2Finvokermanagement_test.go;h=d3c386c6361b2b264f69f21a345aefbd6ea0d193;hb=b8e717a8c264a8b3f73626fc28c81ae65283ae80;hp=63f75096123efdaadd8084430e513de7b5aeb5ef;hpb=c9e08b2a2f647f9f870040570c5e71305f0fb5d2;p=nonrtric%2Fplt%2Fsme.git diff --git a/capifcore/internal/invokermanagement/invokermanagement_test.go b/capifcore/internal/invokermanagement/invokermanagement_test.go index 63f7509..d3c386c 100644 --- a/capifcore/internal/invokermanagement/invokermanagement_test.go +++ b/capifcore/internal/invokermanagement/invokermanagement_test.go @@ -23,8 +23,11 @@ import ( "fmt" "net/http" "os" + "strings" "testing" + "time" + "oransc.org/nonrtric/capifcore/internal/eventsapi" "oransc.org/nonrtric/capifcore/internal/invokermanagementapi" "github.com/labstack/echo/v4" @@ -39,74 +42,50 @@ import ( "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 + aefProfiles := []publishserviceapi.AefProfile{ + getAefProfile("aefId"), + } 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{ + publishedServices := []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", - }, - }, - }, - }, - }, - }, - }, + AefProfiles: &aefProfiles, }, } + publishRegisterMock := publishmocks.PublishRegister{} + publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices) + invokerUnderTest, eventChannel, requestHandler := getEcho(&publishRegisterMock) + invokerInfo := "invoker a" - newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ - ApiInvokerInformation: &invokerInfo, - NotificationDestination: "url", - OnboardingInformation: invokermanagementapi.OnboardingInformation{ - ApiInvokerPublicKey: "key", - }, - ApiList: &apiList, - } + newInvoker := getInvoker(invokerInfo) // 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) + err := result.UnmarshalBodyToObject(&resultInvoker) assert.NoError(t, err, "error unmarshaling response") - assert.Equal(t, "api_invoker_id_invoker_a", *resultInvoker.ApiInvokerId) + wantedInvokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1) + assert.Equal(t, wantedInvokerId, *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) + wantedInvokerSecret := "onboarding_secret_" + strings.Replace(invokerInfo, " ", "_", 1) + assert.Equal(t, wantedInvokerSecret, *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) + assert.True(t, invokerUnderTest.IsInvokerRegistered(wantedInvokerId)) + assert.True(t, invokerUnderTest.VerifyInvokerSecret(wantedInvokerId, wantedInvokerSecret)) + publishRegisterMock.AssertCalled(t, "GetAllPublishedServices") + assert.Equal(t, invokermanagementapi.APIList(publishedServices), *resultInvoker.ApiList) + if invokerEvent, timeout := waitForEvent(eventChannel, 1*time.Second); timeout { + assert.Fail(t, "No event sent") + } else { + assert.Equal(t, *resultInvoker.ApiInvokerId, (*invokerEvent.EventDetail.ApiInvokerIds)[0]) + assert.Equal(t, eventsapi.CAPIFEventAPIINVOKERONBOARDED, invokerEvent.Events) + } // Onboard an invoker missing required NotificationDestination, should get 400 with problem details invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ @@ -120,10 +99,10 @@ func TestOnboardInvoker(t *testing.T) { var problemDetails common29122.ProblemDetails err = result.UnmarshalBodyToObject(&problemDetails) assert.NoError(t, err, "error unmarshaling response") - badRequest := 400 + badRequest := http.StatusBadRequest assert.Equal(t, &badRequest, problemDetails.Status) - errMsg := "Invoker missing required NotificationDestination" - assert.Equal(t, &errMsg, problemDetails.Cause) + assert.Contains(t, *problemDetails.Cause, "missing") + assert.Contains(t, *problemDetails.Cause, "NotificationDestination") // Onboard an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details invalidInvoker = invokermanagementapi.APIInvokerEnrolmentDetails{ @@ -136,121 +115,166 @@ func TestOnboardInvoker(t *testing.T) { 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) + assert.Contains(t, *problemDetails.Cause, "missing") + assert.Contains(t, *problemDetails.Cause, "OnboardingInformation.ApiInvokerPublicKey") } func TestDeleteInvoker(t *testing.T) { - _, requestHandler := getEcho(nil) + invokerUnderTest, eventChannel, requestHandler := getEcho(nil) + invokerId := "invokerId" newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ + ApiInvokerId: &invokerId, 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) + invokerUnderTest.onboardedInvokers[invokerId] = newInvoker + assert.True(t, invokerUnderTest.IsInvokerRegistered(invokerId)) // Delete the invoker - result = testutil.NewRequest().Delete(invokerUrl).Go(t, requestHandler) + result := testutil.NewRequest().Delete("/onboardedInvokers/"+invokerId).Go(t, requestHandler) assert.Equal(t, http.StatusNoContent, result.Code()) + assert.False(t, invokerUnderTest.IsInvokerRegistered(invokerId)) + if invokerEvent, timeout := waitForEvent(eventChannel, 1*time.Second); timeout { + assert.Fail(t, "No event sent") + } else { + assert.Equal(t, invokerId, (*invokerEvent.EventDetail.ApiInvokerIds)[0]) + assert.Equal(t, eventsapi.CAPIFEventAPIINVOKEROFFBOARDED, invokerEvent.Events) + } } func TestUpdateInvoker(t *testing.T) { - _, requestHandler := getEcho(nil) + publishRegisterMock := publishmocks.PublishRegister{} + publishRegisterMock.On("GetAllPublishedServices").Return([]publishserviceapi.ServiceAPIDescription{}) + serviceUnderTest, _, requestHandler := getEcho(&publishRegisterMock) - newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ + invokerId := "invokerId" + invoker := invokermanagementapi.APIInvokerEnrolmentDetails{ + ApiInvokerId: &invokerId, NotificationDestination: "url", OnboardingInformation: invokermanagementapi.OnboardingInformation{ ApiInvokerPublicKey: "key", }, } + serviceUnderTest.onboardedInvokers[invokerId] = invoker - // 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) + // Update the invoker with valid invoker, should return 200 with updated invoker details + newNotifURL := "newUrl" + invoker.NotificationDestination = common29122.Uri(newNotifURL) + newPublicKey := "newPublicKey" + invoker.OnboardingInformation.ApiInvokerPublicKey = newPublicKey + result := testutil.NewRequest().Put("/onboardedInvokers/"+invokerId).WithJsonBody(invoker).Go(t, requestHandler) + var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails 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) + assert.Equal(t, invokerId, *resultInvoker.ApiInvokerId) + assert.Equal(t, newNotifURL, string(resultInvoker.NotificationDestination)) + assert.Equal(t, newPublicKey, 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, + ApiInvokerId: &invokerId, OnboardingInformation: validOnboardingInfo, } - result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler) + result = testutil.NewRequest().Put("/onboardedInvokers/"+invokerId).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 + badRequest := http.StatusBadRequest assert.Equal(t, &badRequest, problemDetails.Status) - errMsg := "Invoker missing required NotificationDestination" - assert.Equal(t, &errMsg, problemDetails.Cause) + assert.Contains(t, *problemDetails.Cause, "missing") + assert.Contains(t, *problemDetails.Cause, "NotificationDestination") // 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) + result = testutil.NewRequest().Put("/onboardedInvokers/"+invokerId).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) + assert.Contains(t, *problemDetails.Cause, "missing") + assert.Contains(t, *problemDetails.Cause, "OnboardingInformation.ApiInvokerPublicKey") // 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) + result = testutil.NewRequest().Put("/onboardedInvokers/"+invokerId).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) + assert.Contains(t, *problemDetails.Cause, "not matching") + assert.Contains(t, *problemDetails.Cause, "ApiInvokerId") - // Update an invoker that has not been onboarded, shold get 404 with problem details + // Update an invoker that has not been onboarded, should get 404 with problem details missingId := "1" - newInvoker.ApiInvokerId = &missingId - result = testutil.NewRequest().Put("/onboardedInvokers/"+missingId).WithJsonBody(newInvoker).Go(t, requestHandler) + invoker.ApiInvokerId = &missingId + result = testutil.NewRequest().Put("/onboardedInvokers/"+missingId).WithJsonBody(invoker).Go(t, requestHandler) assert.Equal(t, http.StatusNotFound, result.Code()) err = result.UnmarshalBodyToObject(&problemDetails) assert.NoError(t, err, "error unmarshaling response") - notFound := 404 + notFound := http.StatusNotFound assert.Equal(t, ¬Found, problemDetails.Status) - errMsg = "The invoker to update has not been onboarded" - assert.Equal(t, &errMsg, problemDetails.Cause) + assert.Contains(t, *problemDetails.Cause, "not been onboarded") + assert.Contains(t, *problemDetails.Cause, "invoker") +} +func TestGetInvokerApiList(t *testing.T) { + aefProfiles1 := []publishserviceapi.AefProfile{ + getAefProfile("aefId"), + } + apiId := "apiId" + apiList := []publishserviceapi.ServiceAPIDescription{ + { + ApiId: &apiId, + AefProfiles: &aefProfiles1, + }, + } + aefProfiles2 := []publishserviceapi.AefProfile{ + getAefProfile("aefId2"), + } + apiId2 := "apiId2" + apiList = append(apiList, publishserviceapi.ServiceAPIDescription{ + ApiId: &apiId2, + AefProfiles: &aefProfiles2, + }) + publishRegisterMock := publishmocks.PublishRegister{} + publishRegisterMock.On("GetAllPublishedServices").Return(apiList) + invokerUnderTest, _, _ := getEcho(&publishRegisterMock) + + invokerInfo := "invoker a" + newInvoker := getInvoker(invokerInfo) + invokerAId := "api_invoker_id_" + strings.ReplaceAll(invokerInfo, " ", "_") + newInvoker.ApiInvokerId = &invokerAId + invokerUnderTest.onboardedInvokers[invokerAId] = newInvoker + invokerInfo = "invoker b" + newInvoker = getInvoker(invokerInfo) + invokerId := "api_invoker_id_" + strings.ReplaceAll(invokerInfo, " ", "_") + newInvoker.ApiInvokerId = &invokerId + invokerUnderTest.onboardedInvokers[invokerId] = newInvoker + + wantedApiList := invokerUnderTest.GetInvokerApiList(invokerAId) + assert.NotNil(t, wantedApiList) + assert.Len(t, *wantedApiList, 2) + assert.Equal(t, apiId, *(*wantedApiList)[0].ApiId) } -func getEcho(apiRegister publishservice.APIRegister) (*InvokerManager, *echo.Echo) { +func getEcho(publishRegister publishservice.PublishRegister) (*InvokerManager, chan eventsapi.EventNotification, *echo.Echo) { swagger, err := invokermanagementapi.GetSwagger() if err != nil { fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err) @@ -259,12 +283,51 @@ func getEcho(apiRegister publishservice.APIRegister) (*InvokerManager, *echo.Ech swagger.Servers = nil - im := NewInvokerManager(apiRegister) + eventChannel := make(chan eventsapi.EventNotification) + im := NewInvokerManager(publishRegister, eventChannel) e := echo.New() e.Use(echomiddleware.Logger()) e.Use(middleware.OapiRequestValidator(swagger)) invokermanagementapi.RegisterHandlers(e, im) - return im, e + return im, eventChannel, e +} + +func getAefProfile(aefId string) publishserviceapi.AefProfile { + return publishserviceapi.AefProfile{ + AefId: aefId, + Versions: []publishserviceapi.Version{ + { + Resources: &[]publishserviceapi.Resource{ + { + CommType: "REQUEST_RESPONSE", + }, + }, + }, + }, + } +} + +func getInvoker(invokerInfo string) invokermanagementapi.APIInvokerEnrolmentDetails { + newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{ + ApiInvokerInformation: &invokerInfo, + NotificationDestination: "url", + OnboardingInformation: invokermanagementapi.OnboardingInformation{ + ApiInvokerPublicKey: "key", + }, + ApiList: nil, + } + return newInvoker +} + +// waitForEvent waits for the channel to receive an event for the specified max timeout. +// Returns true if waiting timed out. +func waitForEvent(ch chan eventsapi.EventNotification, timeout time.Duration) (*eventsapi.EventNotification, bool) { + select { + case event := <-ch: + return &event, false // completed normally + case <-time.After(timeout): + return nil, true // timed out + } }