X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=capifcore%2Finternal%2Fpublishservice%2Fpublishservice_test.go;h=3f1a71f64c1e9899c7deb639773e1c07a2928cba;hb=refs%2Fchanges%2F85%2F12585%2F1;hp=cad151c0c635993593b073c1932fc95da62f3cf4;hpb=37b5fcbb802f06442a9c08c94e709080a747f7ad;p=nonrtric%2Fplt%2Fsme.git diff --git a/capifcore/internal/publishservice/publishservice_test.go b/capifcore/internal/publishservice/publishservice_test.go index cad151c..3f1a71f 100644 --- a/capifcore/internal/publishservice/publishservice_test.go +++ b/capifcore/internal/publishservice/publishservice_test.go @@ -2,7 +2,8 @@ // ========================LICENSE_START================================= // O-RAN-SC // %% -// Copyright (C) 2022: Nordix Foundation +// Copyright (C) 2022-2023: Nordix Foundation +// Copyright (C) 2024: OpenInfra Foundation Europe // %% // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -46,19 +47,49 @@ import ( "github.com/stretchr/testify/mock" ) +func TestUnregisteredService(t *testing.T) { + apfId := "apfId" + serviceRegisterMock := serviceMocks.ServiceRegister{} + serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(false) + + helmManagerMock := helmMocks.HelmManager{} + helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) + _, _, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock) + + // Check no services published + result := testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler) + assert.Equal(t, http.StatusNotFound, result.Code()) + + var resultError common29122.ProblemDetails + err := result.UnmarshalJsonToObject(&resultError) + assert.NoError(t, err, "error unmarshaling response") + + assert.Contains(t, *resultError.Cause, "api is only available for publishers") + assert.Equal(t, http.StatusNotFound, *resultError.Status) +} + func TestPublishUnpublishService(t *testing.T) { + apfId := "apfId" aefId := "aefId" serviceRegisterMock := serviceMocks.ServiceRegister{} serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId"}) + serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true) helmManagerMock := helmMocks.HelmManager{} helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) serviceUnderTest, eventChannel, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock) - // Check no services published for provider + // Check no services published + var resultServices []publishapi.ServiceAPIDescription result := testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler) + assert.Equal(t, http.StatusOK, result.Code()) - assert.Equal(t, http.StatusNotFound, result.Code()) + // Parse JSON from the response body + err := result.UnmarshalJsonToObject(&resultServices) + assert.NoError(t, err, "error unmarshaling response") + + // Check if the parsed array is empty + assert.Zero(t, len(resultServices)) apiName := "app-management" namespace := "namespace" @@ -70,17 +101,16 @@ func TestPublishUnpublishService(t *testing.T) { // Publish a service for provider result = testutil.NewRequest().Post("/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler) - assert.Equal(t, http.StatusCreated, result.Code()) + var resultService publishapi.ServiceAPIDescription - err := result.UnmarshalBodyToObject(&resultService) + + err = result.UnmarshalJsonToObject(&resultService) assert.NoError(t, err, "error unmarshaling response") newApiId := "api_id_" + apiName - assert.Equal(t, *resultService.ApiId, newApiId) + assert.Equal(t, newApiId, *resultService.ApiId) assert.Equal(t, "http://example.com/"+apfId+"/service-apis/"+*resultService.ApiId, result.Recorder.Header().Get(echo.HeaderLocation)) newServiceDescription.ApiId = &newApiId - wantedAPILIst := []publishapi.ServiceAPIDescription{newServiceDescription} - assert.True(t, serviceUnderTest.AreAPIsPublished(&wantedAPILIst)) assert.True(t, serviceUnderTest.IsAPIPublished(aefId, apiName)) serviceRegisterMock.AssertCalled(t, "GetAefsForPublisher", apfId) helmManagerMock.AssertCalled(t, "InstallHelmChart", namespace, repoName, chartName, releaseName) @@ -96,19 +126,30 @@ func TestPublishUnpublishService(t *testing.T) { result = testutil.NewRequest().Get("/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) - err = result.UnmarshalBodyToObject(&resultService) + err = result.UnmarshalJsonToObject(&resultService) assert.NoError(t, err, "error unmarshaling response") assert.Equal(t, *resultService.ApiId, newApiId) + // Publish the same service again should result in Forbidden + result = testutil.NewRequest().Post("/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler) + + assert.Equal(t, http.StatusForbidden, result.Code()) + var resultError common29122.ProblemDetails + err = result.UnmarshalJsonToObject(&resultError) + assert.NoError(t, err, "error unmarshaling response") + assert.Contains(t, *resultError.Cause, "already published") + assert.Equal(t, http.StatusForbidden, *resultError.Status) + // Delete the service helmManagerMock.On("UninstallHelmChart", mock.Anything, mock.Anything).Return(nil) + result = testutil.NewRequest().Delete("/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler) assert.Equal(t, http.StatusNoContent, result.Code()) helmManagerMock.AssertCalled(t, "UninstallHelmChart", namespace, chartName) assert.Empty(t, serviceUnderTest.getAllAefIds()) - // Check no services published + // Check no services published for a provider result = testutil.NewRequest().Get("/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler) if publishEvent, ok := waitForEvent(eventChannel, 1*time.Second); ok { @@ -119,6 +160,18 @@ func TestPublishUnpublishService(t *testing.T) { } assert.Equal(t, http.StatusNotFound, result.Code()) + + // Check no services published + result = testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler) + assert.Equal(t, http.StatusOK, result.Code()) + + // Parse JSON from the response body + var responseArray []publishapi.ServiceAPIDescription + err = result.UnmarshalJsonToObject(&responseArray) + assert.NoError(t, err, "error unmarshaling response") + + // Check if the parsed array is empty + assert.Zero(t, len(responseArray)) } func TestPostUnpublishedServiceWithUnregisteredFunction(t *testing.T) { @@ -126,6 +179,7 @@ func TestPostUnpublishedServiceWithUnregisteredFunction(t *testing.T) { aefId := "aefId" serviceRegisterMock := serviceMocks.ServiceRegister{} serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{"otherAefId"}) + serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true) _, _, requestHandler := getEcho(&serviceRegisterMock, nil) newServiceDescription := getServiceAPIDescription(aefId, "apiName", "description") @@ -135,12 +189,11 @@ func TestPostUnpublishedServiceWithUnregisteredFunction(t *testing.T) { assert.Equal(t, http.StatusNotFound, result.Code()) var resultError common29122.ProblemDetails - err := result.UnmarshalBodyToObject(&resultError) + err := result.UnmarshalJsonToObject(&resultError) assert.NoError(t, err, "error unmarshaling response") assert.Contains(t, *resultError.Cause, aefId) assert.Contains(t, *resultError.Cause, "not registered") - notFound := http.StatusNotFound - assert.Equal(t, ¬Found, resultError.Status) + assert.Equal(t, http.StatusNotFound, *resultError.Status) } func TestGetServices(t *testing.T) { @@ -148,12 +201,21 @@ func TestGetServices(t *testing.T) { aefId := "aefId" serviceRegisterMock := serviceMocks.ServiceRegister{} serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId}) + serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true) _, _, requestHandler := getEcho(&serviceRegisterMock, nil) - // Check no services published for provider + // Check no services published + var resultServices []publishapi.ServiceAPIDescription + result := testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler) + assert.Equal(t, http.StatusOK, result.Code()) - assert.Equal(t, http.StatusNotFound, result.Code()) + // Parse JSON from the response body + err := result.UnmarshalJsonToObject(&resultServices) + assert.NoError(t, err, "error unmarshaling response") + + // Check if the parsed array is empty + assert.Zero(t, len(resultServices)) serviceDescription1 := getServiceAPIDescription(aefId, "api1", "Description") serviceDescription2 := getServiceAPIDescription(aefId, "api2", "Description") @@ -165,14 +227,16 @@ func TestGetServices(t *testing.T) { // Get all services for provider result = testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) - var resultServices []publishapi.ServiceAPIDescription - err := result.UnmarshalBodyToObject(&resultServices) + + err = result.UnmarshalJsonToObject(&resultServices) assert.NoError(t, err, "error unmarshaling response") + assert.Len(t, resultServices, 2) apiId1 := "api_id_api1" serviceDescription1.ApiId = &apiId1 apiId2 := "api_id_api2" serviceDescription2.ApiId = &apiId2 + assert.Contains(t, resultServices, serviceDescription1) assert.Contains(t, resultServices, serviceDescription2) } @@ -194,34 +258,140 @@ func TestGetPublishedServices(t *testing.T) { assert.Len(t, result, 2) } +func TestGetAllowedServices(t *testing.T) { + serviceUnderTest := NewPublishService(nil, nil, nil) + + aefProfiles1 := []publishapi.AefProfile{} + apiId1 := "apiId1" + aefProfiles2 := []publishapi.AefProfile{} + apiId2 := "apiId2" + aefProfiles3 := []publishapi.AefProfile{} + apiId3 := "apiId3" + aefProfiles4 := []publishapi.AefProfile{} + apiId4 := "apiId4" + + serviceUnderTest.publishedServices["publisher1"] = []publishapi.ServiceAPIDescription{ + { + ApiId: &apiId1, + AefProfiles: &aefProfiles1, + }, + { + ApiId: &apiId2, + AefProfiles: &aefProfiles2, + }, + { + ApiId: &apiId3, + AefProfiles: &aefProfiles3, + }, + { + ApiId: &apiId4, + AefProfiles: &aefProfiles4, + }, + } + + serviceDescription := publishapi.ServiceAPIDescription{ + ApiId: &apiId4, + AefProfiles: &aefProfiles4, + } + serviceUnderTest.publishedServices["publisher2"] = []publishapi.ServiceAPIDescription{ + serviceDescription, + } + + allowedApiList := []publishapi.ServiceAPIDescription{ + { + ApiId: &apiId2, + AefProfiles: &aefProfiles2, + }, + { + ApiId: &apiId3, + AefProfiles: &aefProfiles3, + }, + } + + result := serviceUnderTest.GetAllowedPublishedServices(allowedApiList) + assert.Len(t, result, 2) + + result = serviceUnderTest.GetAllowedPublishedServices(nil) + assert.Len(t, result, 0) + + result = serviceUnderTest.GetAllowedPublishedServices([]publishapi.ServiceAPIDescription{}) + assert.Len(t, result, 0) + + // Create a list with no ApiIds + badApiList := []publishapi.ServiceAPIDescription{ + { + }, + { + }, + } + result = serviceUnderTest.GetAllowedPublishedServices(badApiList) + assert.Len(t, result, 0) +} + func TestUpdateDescription(t *testing.T) { apfId := "apfId" serviceApiId := "serviceApiId" aefId := "aefId" apiName := "apiName" description := "description" + serviceRegisterMock := serviceMocks.ServiceRegister{} - serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId"}) + serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId", "aefIdNew"}) + serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true) helmManagerMock := helmMocks.HelmManager{} helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) serviceUnderTest, eventChannel, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock) - serviceDescription := getServiceAPIDescription(aefId, apiName, description) serviceDescription.ApiId = &serviceApiId serviceUnderTest.publishedServices[apfId] = []publishapi.ServiceAPIDescription{serviceDescription} + (*serviceDescription.AefProfiles)[0].AefId = aefId //Modify the service updatedServiceDescription := getServiceAPIDescription(aefId, apiName, description) - updatedServiceDescription.ApiId = &description + updatedServiceDescription.ApiId = &serviceApiId + (*updatedServiceDescription.AefProfiles)[0].AefId = aefId newDescription := "new description" updatedServiceDescription.Description = &newDescription + newDomainName := "new domainName" + (*updatedServiceDescription.AefProfiles)[0].DomainName = &newDomainName + + newProfileDomain := "new profile Domain name" + var protocol publishapi.Protocol = "HTTP_1_1" + + test := append(*updatedServiceDescription.AefProfiles, publishapi.AefProfile{ + AefId: "aefIdNew", + DomainName: &newProfileDomain, + Protocol: &protocol, + Versions: []publishapi.Version{ + { + ApiVersion: "v1", + Resources: &[]publishapi.Resource{ + { + CommType: "REQUEST_RESPONSE", + Operations: &[]publishapi.Operation{ + "POST", + }, + ResourceName: "app", + Uri: "app", + }, + }, + }, + }, + }, + ) + + updatedServiceDescription.AefProfiles = &test + result := testutil.NewRequest().Put("/"+apfId+"/service-apis/"+serviceApiId).WithJsonBody(updatedServiceDescription).Go(t, requestHandler) var resultService publishapi.ServiceAPIDescription assert.Equal(t, http.StatusOK, result.Code()) - err := result.UnmarshalBodyToObject(&resultService) + err := result.UnmarshalJsonToObject(&resultService) assert.NoError(t, err, "error unmarshaling response") - assert.Equal(t, resultService.Description, &newDescription) + assert.Equal(t, newDescription, *resultService.Description) + assert.Equal(t, newDomainName, *(*resultService.AefProfiles)[0].DomainName) + assert.Equal(t, "aefIdNew", (*resultService.AefProfiles)[1].AefId) + assert.True(t, serviceUnderTest.IsAPIPublished("aefIdNew", "path")) if publishEvent, ok := waitForEvent(eventChannel, 1*time.Second); ok { assert.Fail(t, "No event sent") @@ -231,6 +401,176 @@ func TestUpdateDescription(t *testing.T) { } } +func TestFailedUpdateDescription(t *testing.T) { + apfId := "apfId" + serviceApiId := "serviceApiId" + // Trying to update a different serviceApiId will cause a 400 error + updatedServiceApiId := "updatedServiceApiId" + aefId := "aefId" + apiName := "apiName" + description := "description" + + serviceRegisterMock := serviceMocks.ServiceRegister{} + serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId", "aefIdNew"}) + serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true) + helmManagerMock := helmMocks.HelmManager{} + helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) + serviceUnderTest, _, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock) + serviceDescription := getServiceAPIDescription(aefId, apiName, description) + serviceDescription.ApiId = &serviceApiId + serviceUnderTest.publishedServices[apfId] = []publishapi.ServiceAPIDescription{serviceDescription} + (*serviceDescription.AefProfiles)[0].AefId = aefId + + // Modify the service + updatedServiceDescription := getServiceAPIDescription(aefId, apiName, description) + updatedServiceDescription.ApiId = &updatedServiceApiId + (*updatedServiceDescription.AefProfiles)[0].AefId = aefId + newDescription := "new description" + updatedServiceDescription.Description = &newDescription + newDomainName := "new domainName" + (*updatedServiceDescription.AefProfiles)[0].DomainName = &newDomainName + + newProfileDomain := "new profile Domain name" + var protocol publishapi.Protocol = "HTTP_1_1" + + test := append(*updatedServiceDescription.AefProfiles, publishapi.AefProfile{ + AefId: "aefIdNew", + DomainName: &newProfileDomain, + Protocol: &protocol, + Versions: []publishapi.Version{ + { + ApiVersion: "v1", + Resources: &[]publishapi.Resource{ + { + CommType: "REQUEST_RESPONSE", + Operations: &[]publishapi.Operation{ + "POST", + }, + ResourceName: "app", + Uri: "app", + }, + }, + }, + }, + }, + ) + updatedServiceDescription.AefProfiles = &test + + result := testutil.NewRequest().Put("/"+apfId+"/service-apis/"+serviceApiId).WithJsonBody(updatedServiceDescription).Go(t, requestHandler) + assert.Equal(t, http.StatusBadRequest, result.Code()) + + var resultError common29122.ProblemDetails + err := result.UnmarshalJsonToObject(&resultError) + assert.NoError(t, err, "error unmarshaling response") + + assert.Contains(t, *resultError.Cause, "ServiceAPIDescription ApiId doesn't match path parameter") + assert.Equal(t, http.StatusBadRequest, *resultError.Status) +} + +func TestUpdateValidServiceWithDeletedFunction(t *testing.T) { + apfId := "apfId" + serviceApiId := "serviceApiId" + aefId := "aefId" + apiName := "apiName" + description := "description" + + serviceRegisterMock := serviceMocks.ServiceRegister{} + serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true) + serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId", "aefIdNew"}) + helmManagerMock := helmMocks.HelmManager{} + helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) + serviceUnderTest, _, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock) + + serviceDescription := getServiceAPIDescription(aefId, apiName, description) + serviceDescription.ApiId = &serviceApiId + (*serviceDescription.AefProfiles)[0].AefId = aefId + + newProfileDomain := "new profile Domain name" + var protocol publishapi.Protocol = "HTTP_1_1" + test := append(*serviceDescription.AefProfiles, publishapi.AefProfile{ + AefId: "aefIdNew", + DomainName: &newProfileDomain, + Protocol: &protocol, + Versions: []publishapi.Version{ + { + ApiVersion: "v1", + Resources: &[]publishapi.Resource{ + { + CommType: "REQUEST_RESPONSE", + Operations: &[]publishapi.Operation{ + "POST", + }, + ResourceName: "app", + Uri: "app", + }, + }, + }, + }, + }, + ) + serviceDescription.AefProfiles = &test + serviceUnderTest.publishedServices[apfId] = []publishapi.ServiceAPIDescription{serviceDescription} + + //Modify the service + updatedServiceDescription := getServiceAPIDescription(aefId, apiName, description) + updatedServiceDescription.ApiId = &serviceApiId + test1 := append(*updatedServiceDescription.AefProfiles, publishapi.AefProfile{ + AefId: "aefIdNew", + DomainName: &newProfileDomain, + Protocol: &protocol, + Versions: []publishapi.Version{ + { + ApiVersion: "v1", + Resources: &[]publishapi.Resource{ + { + CommType: "REQUEST_RESPONSE", + Operations: &[]publishapi.Operation{ + "POST", + }, + ResourceName: "app", + Uri: "app", + }, + }, + }, + }, + }, + ) + updatedServiceDescription.AefProfiles = &test1 + testFunc := []publishapi.AefProfile{ + (*updatedServiceDescription.AefProfiles)[1], + } + + updatedServiceDescription.AefProfiles = &testFunc + result := testutil.NewRequest().Put("/"+apfId+"/service-apis/"+serviceApiId).WithJsonBody(updatedServiceDescription).Go(t, requestHandler) + var resultService publishapi.ServiceAPIDescription + assert.Equal(t, http.StatusOK, result.Code()) + err := result.UnmarshalJsonToObject(&resultService) + assert.NoError(t, err, "error unmarshaling response") + assert.Len(t, (*resultService.AefProfiles), 1) + assert.False(t, serviceUnderTest.IsAPIPublished("aefId", "path")) + +} + +func TestPublishInvalidService(t *testing.T) { + apfId := "apfId" + serviceRegisterMock := serviceMocks.ServiceRegister{} + serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true) + + _, _, requestHandler := getEcho(&serviceRegisterMock, nil) + newServiceDescription := getServiceAPIDescription("aefId", " ", "description") + + // Publish a service + result := testutil.NewRequest().Post("/apfId/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler) + + assert.Equal(t, http.StatusBadRequest, result.Code()) + var resultError common29122.ProblemDetails + err := result.UnmarshalJsonToObject(&resultError) + assert.NoError(t, err, "error unmarshaling response") + assert.Contains(t, *resultError.Cause, "missing") + assert.Contains(t, *resultError.Cause, "apiName") + assert.Equal(t, http.StatusBadRequest, *resultError.Status) + +} func getEcho(serviceRegister providermanagement.ServiceRegister, helmManager helmmanagement.HelmManager) (*PublishService, chan eventsapi.EventNotification, *echo.Echo) { swagger, err := publishapi.GetSwagger() if err != nil {