NONRTRIC-946: Fix Capifcore intersection panic
[nonrtric/plt/sme.git] / capifcore / internal / publishservice / publishservice_test.go
1 // -
2 //   ========================LICENSE_START=================================
3 //   O-RAN-SC
4 //   %%
5 //   Copyright (C) 2022-2023: Nordix Foundation
6 //   Copyright (C) 2024: OpenInfra Foundation Europe
7 //   %%
8 //   Licensed under the Apache License, Version 2.0 (the "License");
9 //   you may not use this file except in compliance with the License.
10 //   You may obtain a copy of the License at
11 //
12 //        http://www.apache.org/licenses/LICENSE-2.0
13 //
14 //   Unless required by applicable law or agreed to in writing, software
15 //   distributed under the License is distributed on an "AS IS" BASIS,
16 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 //   See the License for the specific language governing permissions and
18 //   limitations under the License.
19 //   ========================LICENSE_END===================================
20 //
21
22 package publishservice
23
24 import (
25         "fmt"
26         "net/http"
27         "os"
28         "testing"
29         "time"
30
31         "oransc.org/nonrtric/capifcore/internal/common29122"
32         "oransc.org/nonrtric/capifcore/internal/eventsapi"
33         "oransc.org/nonrtric/capifcore/internal/providermanagement"
34
35         "github.com/labstack/echo/v4"
36
37         publishapi "oransc.org/nonrtric/capifcore/internal/publishserviceapi"
38
39         "oransc.org/nonrtric/capifcore/internal/helmmanagement"
40         helmMocks "oransc.org/nonrtric/capifcore/internal/helmmanagement/mocks"
41         serviceMocks "oransc.org/nonrtric/capifcore/internal/providermanagement/mocks"
42
43         "github.com/deepmap/oapi-codegen/pkg/middleware"
44         "github.com/deepmap/oapi-codegen/pkg/testutil"
45         echomiddleware "github.com/labstack/echo/v4/middleware"
46         "github.com/stretchr/testify/assert"
47         "github.com/stretchr/testify/mock"
48 )
49
50 func TestUnregisteredService(t *testing.T) {
51         apfId := "apfId"
52         serviceRegisterMock := serviceMocks.ServiceRegister{}
53         serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(false)
54
55         helmManagerMock := helmMocks.HelmManager{}
56         helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
57         _, _, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock)
58
59         // Check no services published
60         result := testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler)
61         assert.Equal(t, http.StatusNotFound, result.Code())
62
63         var resultError common29122.ProblemDetails
64         err := result.UnmarshalJsonToObject(&resultError)
65         assert.NoError(t, err, "error unmarshaling response")
66
67         assert.Contains(t, *resultError.Cause, "api is only available for publishers")
68         assert.Equal(t, http.StatusNotFound, *resultError.Status)
69 }
70
71 func TestPublishUnpublishService(t *testing.T) {
72
73         apfId := "apfId"
74         aefId := "aefId"
75         serviceRegisterMock := serviceMocks.ServiceRegister{}
76         serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId"})
77         serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
78         helmManagerMock := helmMocks.HelmManager{}
79         helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
80         serviceUnderTest, eventChannel, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock)
81
82         // Check no services published
83         var resultServices []publishapi.ServiceAPIDescription
84         result := testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler)
85         assert.Equal(t, http.StatusOK, result.Code())
86
87         // Parse JSON from the response body
88         err := result.UnmarshalJsonToObject(&resultServices)
89         assert.NoError(t, err, "error unmarshaling response")
90
91         // Check if the parsed array is empty
92         assert.Zero(t, len(resultServices))
93
94         apiName := "app-management"
95         namespace := "namespace"
96         repoName := "repoName"
97         chartName := "chartName"
98         releaseName := "releaseName"
99         description := fmt.Sprintf("Description,%s,%s,%s,%s", namespace, repoName, chartName, releaseName)
100         newServiceDescription := getServiceAPIDescription(aefId, apiName, description)
101
102         // Publish a service for provider
103         result = testutil.NewRequest().Post("/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
104         assert.Equal(t, http.StatusCreated, result.Code())
105
106         var resultService publishapi.ServiceAPIDescription
107
108         err = result.UnmarshalJsonToObject(&resultService)
109         assert.NoError(t, err, "error unmarshaling response")
110         newApiId := "api_id_" + apiName
111         assert.Equal(t, newApiId, *resultService.ApiId)
112         assert.Equal(t, "http://example.com/"+apfId+"/service-apis/"+*resultService.ApiId, result.Recorder.Header().Get(echo.HeaderLocation))
113         newServiceDescription.ApiId = &newApiId
114         assert.True(t, serviceUnderTest.IsAPIPublished(aefId, apiName))
115         serviceRegisterMock.AssertCalled(t, "GetAefsForPublisher", apfId)
116         helmManagerMock.AssertCalled(t, "InstallHelmChart", namespace, repoName, chartName, releaseName)
117         assert.ElementsMatch(t, []string{aefId}, serviceUnderTest.getAllAefIds())
118         if publishEvent, ok := waitForEvent(eventChannel, 1*time.Second); ok {
119                 assert.Fail(t, "No event sent")
120         } else {
121                 assert.Equal(t, *resultService.ApiId, (*publishEvent.EventDetail.ApiIds)[0])
122                 assert.Equal(t, eventsapi.CAPIFEventSERVICEAPIAVAILABLE, publishEvent.Events)
123         }
124
125         // Check that the service is published for the provider
126         result = testutil.NewRequest().Get("/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler)
127
128         assert.Equal(t, http.StatusOK, result.Code())
129         err = result.UnmarshalJsonToObject(&resultService)
130         assert.NoError(t, err, "error unmarshaling response")
131         assert.Equal(t, *resultService.ApiId, newApiId)
132
133         // Publish the same service again should result in Forbidden
134         result = testutil.NewRequest().Post("/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
135
136         assert.Equal(t, http.StatusForbidden, result.Code())
137         var resultError common29122.ProblemDetails
138         err = result.UnmarshalJsonToObject(&resultError)
139         assert.NoError(t, err, "error unmarshaling response")
140         assert.Contains(t, *resultError.Cause, "already published")
141         assert.Equal(t, http.StatusForbidden, *resultError.Status)
142
143         // Delete the service
144         helmManagerMock.On("UninstallHelmChart", mock.Anything, mock.Anything).Return(nil)
145
146         result = testutil.NewRequest().Delete("/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler)
147
148         assert.Equal(t, http.StatusNoContent, result.Code())
149         helmManagerMock.AssertCalled(t, "UninstallHelmChart", namespace, chartName)
150         assert.Empty(t, serviceUnderTest.getAllAefIds())
151
152         // Check no services published for a provider
153         result = testutil.NewRequest().Get("/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler)
154
155         if publishEvent, ok := waitForEvent(eventChannel, 1*time.Second); ok {
156                 assert.Fail(t, "No event sent")
157         } else {
158                 assert.Equal(t, *resultService.ApiId, (*publishEvent.EventDetail.ApiIds)[0])
159                 assert.Equal(t, eventsapi.CAPIFEventSERVICEAPIUNAVAILABLE, publishEvent.Events)
160         }
161
162         assert.Equal(t, http.StatusNotFound, result.Code())
163
164         // Check no services published
165         result = testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler)
166         assert.Equal(t, http.StatusOK, result.Code())
167
168         // Parse JSON from the response body
169         var responseArray []publishapi.ServiceAPIDescription
170         err = result.UnmarshalJsonToObject(&responseArray)
171         assert.NoError(t, err, "error unmarshaling response")
172
173         // Check if the parsed array is empty
174         assert.Zero(t, len(responseArray))
175 }
176
177 func TestPostUnpublishedServiceWithUnregisteredFunction(t *testing.T) {
178         apfId := "apfId"
179         aefId := "aefId"
180         serviceRegisterMock := serviceMocks.ServiceRegister{}
181         serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{"otherAefId"})
182         serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
183         _, _, requestHandler := getEcho(&serviceRegisterMock, nil)
184
185         newServiceDescription := getServiceAPIDescription(aefId, "apiName", "description")
186
187         // Publish a service
188         result := testutil.NewRequest().Post("/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
189
190         assert.Equal(t, http.StatusNotFound, result.Code())
191         var resultError common29122.ProblemDetails
192         err := result.UnmarshalJsonToObject(&resultError)
193         assert.NoError(t, err, "error unmarshaling response")
194         assert.Contains(t, *resultError.Cause, aefId)
195         assert.Contains(t, *resultError.Cause, "not registered")
196         assert.Equal(t, http.StatusNotFound, *resultError.Status)
197 }
198
199 func TestGetServices(t *testing.T) {
200         apfId := "apfId"
201         aefId := "aefId"
202         serviceRegisterMock := serviceMocks.ServiceRegister{}
203         serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId})
204         serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
205         _, _, requestHandler := getEcho(&serviceRegisterMock, nil)
206
207         // Check no services published
208         var resultServices []publishapi.ServiceAPIDescription
209
210         result := testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler)
211         assert.Equal(t, http.StatusOK, result.Code())
212
213         // Parse JSON from the response body
214         err := result.UnmarshalJsonToObject(&resultServices)
215         assert.NoError(t, err, "error unmarshaling response")
216
217         // Check if the parsed array is empty
218         assert.Zero(t, len(resultServices))
219
220         serviceDescription1 := getServiceAPIDescription(aefId, "api1", "Description")
221         serviceDescription2 := getServiceAPIDescription(aefId, "api2", "Description")
222
223         // Publish a service for provider
224         testutil.NewRequest().Post("/"+apfId+"/service-apis").WithJsonBody(serviceDescription1).Go(t, requestHandler)
225         testutil.NewRequest().Post("/"+apfId+"/service-apis").WithJsonBody(serviceDescription2).Go(t, requestHandler)
226
227         // Get all services for provider
228         result = testutil.NewRequest().Get("/"+apfId+"/service-apis").Go(t, requestHandler)
229         assert.Equal(t, http.StatusOK, result.Code())
230
231         err = result.UnmarshalJsonToObject(&resultServices)
232         assert.NoError(t, err, "error unmarshaling response")
233
234         assert.Len(t, resultServices, 2)
235         apiId1 := "api_id_api1"
236         serviceDescription1.ApiId = &apiId1
237         apiId2 := "api_id_api2"
238         serviceDescription2.ApiId = &apiId2
239
240         assert.Contains(t, resultServices, serviceDescription1)
241         assert.Contains(t, resultServices, serviceDescription2)
242 }
243
244 func TestGetPublishedServices(t *testing.T) {
245         serviceUnderTest := NewPublishService(nil, nil, nil)
246
247         profiles := make([]publishapi.AefProfile, 1)
248         serviceDescription := publishapi.ServiceAPIDescription{
249                 AefProfiles: &profiles,
250         }
251         serviceUnderTest.publishedServices["publisher1"] = []publishapi.ServiceAPIDescription{
252                 serviceDescription,
253         }
254         serviceUnderTest.publishedServices["publisher2"] = []publishapi.ServiceAPIDescription{
255                 serviceDescription,
256         }
257         result := serviceUnderTest.GetAllPublishedServices()
258         assert.Len(t, result, 2)
259 }
260
261 func TestGetAllowedServices(t *testing.T) {
262         serviceUnderTest := NewPublishService(nil, nil, nil)
263
264         aefProfiles1 := []publishapi.AefProfile{}
265         apiId1 := "apiId1"
266         aefProfiles2 := []publishapi.AefProfile{}
267         apiId2 := "apiId2"
268         aefProfiles3 := []publishapi.AefProfile{}
269         apiId3 := "apiId3"
270         aefProfiles4 := []publishapi.AefProfile{}
271         apiId4 := "apiId4"
272
273         serviceUnderTest.publishedServices["publisher1"] = []publishapi.ServiceAPIDescription{
274                 {
275                         ApiId:       &apiId1,
276                         AefProfiles: &aefProfiles1,
277                 },
278                 {
279                         ApiId:       &apiId2,
280                         AefProfiles: &aefProfiles2,
281                 },
282                 {
283                         ApiId:       &apiId3,
284                         AefProfiles: &aefProfiles3,
285                 },
286                 {
287                         ApiId:       &apiId4,
288                         AefProfiles: &aefProfiles4,
289                 },
290         }
291
292         serviceDescription := publishapi.ServiceAPIDescription{
293                 ApiId:       &apiId4,
294                 AefProfiles: &aefProfiles4,
295         }
296         serviceUnderTest.publishedServices["publisher2"] = []publishapi.ServiceAPIDescription{
297                 serviceDescription,
298         }
299
300         allowedApiList := []publishapi.ServiceAPIDescription{
301                 {
302                         ApiId:       &apiId2,
303                         AefProfiles: &aefProfiles2,
304                 },
305                 {
306                         ApiId:       &apiId3,
307                         AefProfiles: &aefProfiles3,
308                 },
309         }
310
311         result := serviceUnderTest.GetAllowedPublishedServices(allowedApiList)
312         assert.Len(t, result, 2)
313
314         result = serviceUnderTest.GetAllowedPublishedServices(nil)
315         assert.Len(t, result, 0)
316
317         result = serviceUnderTest.GetAllowedPublishedServices([]publishapi.ServiceAPIDescription{})
318         assert.Len(t, result, 0)
319
320         // Create a list with no ApiIds
321         badApiList := []publishapi.ServiceAPIDescription{
322                 {
323                 },
324                 {
325                 },
326         }
327         result = serviceUnderTest.GetAllowedPublishedServices(badApiList)
328         assert.Len(t, result, 0)
329 }
330
331 func TestUpdateDescription(t *testing.T) {
332         apfId := "apfId"
333         serviceApiId := "serviceApiId"
334         aefId := "aefId"
335         apiName := "apiName"
336         description := "description"
337
338         serviceRegisterMock := serviceMocks.ServiceRegister{}
339         serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId", "aefIdNew"})
340         serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
341         helmManagerMock := helmMocks.HelmManager{}
342         helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
343         serviceUnderTest, eventChannel, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock)
344         serviceDescription := getServiceAPIDescription(aefId, apiName, description)
345         serviceDescription.ApiId = &serviceApiId
346         serviceUnderTest.publishedServices[apfId] = []publishapi.ServiceAPIDescription{serviceDescription}
347         (*serviceDescription.AefProfiles)[0].AefId = aefId
348
349         //Modify the service
350         updatedServiceDescription := getServiceAPIDescription(aefId, apiName, description)
351         updatedServiceDescription.ApiId = &serviceApiId
352         (*updatedServiceDescription.AefProfiles)[0].AefId = aefId
353         newDescription := "new description"
354         updatedServiceDescription.Description = &newDescription
355         newDomainName := "new domainName"
356         (*updatedServiceDescription.AefProfiles)[0].DomainName = &newDomainName
357
358         newProfileDomain := "new profile Domain name"
359         var protocol publishapi.Protocol = "HTTP_1_1"
360
361         test := append(*updatedServiceDescription.AefProfiles, publishapi.AefProfile{
362                 AefId:      "aefIdNew",
363                 DomainName: &newProfileDomain,
364                 Protocol:   &protocol,
365                 Versions: []publishapi.Version{
366                         {
367                                 ApiVersion: "v1",
368                                 Resources: &[]publishapi.Resource{
369                                         {
370                                                 CommType: "REQUEST_RESPONSE",
371                                                 Operations: &[]publishapi.Operation{
372                                                         "POST",
373                                                 },
374                                                 ResourceName: "app",
375                                                 Uri:          "app",
376                                         },
377                                 },
378                         },
379                 },
380         },
381         )
382
383         updatedServiceDescription.AefProfiles = &test
384
385         result := testutil.NewRequest().Put("/"+apfId+"/service-apis/"+serviceApiId).WithJsonBody(updatedServiceDescription).Go(t, requestHandler)
386
387         var resultService publishapi.ServiceAPIDescription
388         assert.Equal(t, http.StatusOK, result.Code())
389         err := result.UnmarshalJsonToObject(&resultService)
390         assert.NoError(t, err, "error unmarshaling response")
391         assert.Equal(t, newDescription, *resultService.Description)
392         assert.Equal(t, newDomainName, *(*resultService.AefProfiles)[0].DomainName)
393         assert.Equal(t, "aefIdNew", (*resultService.AefProfiles)[1].AefId)
394         assert.True(t, serviceUnderTest.IsAPIPublished("aefIdNew", "path"))
395
396         if publishEvent, ok := waitForEvent(eventChannel, 1*time.Second); ok {
397                 assert.Fail(t, "No event sent")
398         } else {
399                 assert.Equal(t, *resultService.ApiId, (*publishEvent.EventDetail.ApiIds)[0])
400                 assert.Equal(t, eventsapi.CAPIFEventSERVICEAPIUPDATE, publishEvent.Events)
401         }
402 }
403
404 func TestFailedUpdateDescription(t *testing.T) {
405         apfId := "apfId"
406         serviceApiId := "serviceApiId"
407         // Trying to update a different serviceApiId will cause a 400 error
408         updatedServiceApiId := "updatedServiceApiId"
409         aefId := "aefId"
410         apiName := "apiName"
411         description := "description"
412
413         serviceRegisterMock := serviceMocks.ServiceRegister{}
414         serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId", "aefIdNew"})
415         serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
416         helmManagerMock := helmMocks.HelmManager{}
417         helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
418         serviceUnderTest, _, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock)
419         serviceDescription := getServiceAPIDescription(aefId, apiName, description)
420         serviceDescription.ApiId = &serviceApiId
421         serviceUnderTest.publishedServices[apfId] = []publishapi.ServiceAPIDescription{serviceDescription}
422         (*serviceDescription.AefProfiles)[0].AefId = aefId
423
424         // Modify the service
425         updatedServiceDescription := getServiceAPIDescription(aefId, apiName, description)
426         updatedServiceDescription.ApiId = &updatedServiceApiId
427         (*updatedServiceDescription.AefProfiles)[0].AefId = aefId
428         newDescription := "new description"
429         updatedServiceDescription.Description = &newDescription
430         newDomainName := "new domainName"
431         (*updatedServiceDescription.AefProfiles)[0].DomainName = &newDomainName
432
433         newProfileDomain := "new profile Domain name"
434         var protocol publishapi.Protocol = "HTTP_1_1"
435
436         test := append(*updatedServiceDescription.AefProfiles, publishapi.AefProfile{
437                 AefId:      "aefIdNew",
438                 DomainName: &newProfileDomain,
439                 Protocol:   &protocol,
440                 Versions: []publishapi.Version{
441                         {
442                                 ApiVersion: "v1",
443                                 Resources: &[]publishapi.Resource{
444                                         {
445                                                 CommType: "REQUEST_RESPONSE",
446                                                 Operations: &[]publishapi.Operation{
447                                                         "POST",
448                                                 },
449                                                 ResourceName: "app",
450                                                 Uri:          "app",
451                                         },
452                                 },
453                         },
454                 },
455         },
456         )
457         updatedServiceDescription.AefProfiles = &test
458
459         result := testutil.NewRequest().Put("/"+apfId+"/service-apis/"+serviceApiId).WithJsonBody(updatedServiceDescription).Go(t, requestHandler)
460         assert.Equal(t, http.StatusBadRequest, result.Code())
461
462         var resultError common29122.ProblemDetails
463         err := result.UnmarshalJsonToObject(&resultError)
464         assert.NoError(t, err, "error unmarshaling response")
465
466         assert.Contains(t, *resultError.Cause, "ServiceAPIDescription ApiId doesn't match path parameter")
467         assert.Equal(t, http.StatusBadRequest, *resultError.Status)
468 }
469
470 func TestUpdateValidServiceWithDeletedFunction(t *testing.T) {
471         apfId := "apfId"
472         serviceApiId := "serviceApiId"
473         aefId := "aefId"
474         apiName := "apiName"
475         description := "description"
476
477         serviceRegisterMock := serviceMocks.ServiceRegister{}
478         serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
479         serviceRegisterMock.On("GetAefsForPublisher", apfId).Return([]string{aefId, "otherAefId", "aefIdNew"})
480         helmManagerMock := helmMocks.HelmManager{}
481         helmManagerMock.On("InstallHelmChart", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
482         serviceUnderTest, _, requestHandler := getEcho(&serviceRegisterMock, &helmManagerMock)
483
484         serviceDescription := getServiceAPIDescription(aefId, apiName, description)
485         serviceDescription.ApiId = &serviceApiId
486         (*serviceDescription.AefProfiles)[0].AefId = aefId
487
488         newProfileDomain := "new profile Domain name"
489         var protocol publishapi.Protocol = "HTTP_1_1"
490         test := append(*serviceDescription.AefProfiles, publishapi.AefProfile{
491                 AefId:      "aefIdNew",
492                 DomainName: &newProfileDomain,
493                 Protocol:   &protocol,
494                 Versions: []publishapi.Version{
495                         {
496                                 ApiVersion: "v1",
497                                 Resources: &[]publishapi.Resource{
498                                         {
499                                                 CommType: "REQUEST_RESPONSE",
500                                                 Operations: &[]publishapi.Operation{
501                                                         "POST",
502                                                 },
503                                                 ResourceName: "app",
504                                                 Uri:          "app",
505                                         },
506                                 },
507                         },
508                 },
509         },
510         )
511         serviceDescription.AefProfiles = &test
512         serviceUnderTest.publishedServices[apfId] = []publishapi.ServiceAPIDescription{serviceDescription}
513
514         //Modify the service
515         updatedServiceDescription := getServiceAPIDescription(aefId, apiName, description)
516         updatedServiceDescription.ApiId = &serviceApiId
517         test1 := append(*updatedServiceDescription.AefProfiles, publishapi.AefProfile{
518                 AefId:      "aefIdNew",
519                 DomainName: &newProfileDomain,
520                 Protocol:   &protocol,
521                 Versions: []publishapi.Version{
522                         {
523                                 ApiVersion: "v1",
524                                 Resources: &[]publishapi.Resource{
525                                         {
526                                                 CommType: "REQUEST_RESPONSE",
527                                                 Operations: &[]publishapi.Operation{
528                                                         "POST",
529                                                 },
530                                                 ResourceName: "app",
531                                                 Uri:          "app",
532                                         },
533                                 },
534                         },
535                 },
536         },
537         )
538         updatedServiceDescription.AefProfiles = &test1
539         testFunc := []publishapi.AefProfile{
540                 (*updatedServiceDescription.AefProfiles)[1],
541         }
542
543         updatedServiceDescription.AefProfiles = &testFunc
544         result := testutil.NewRequest().Put("/"+apfId+"/service-apis/"+serviceApiId).WithJsonBody(updatedServiceDescription).Go(t, requestHandler)
545         var resultService publishapi.ServiceAPIDescription
546         assert.Equal(t, http.StatusOK, result.Code())
547         err := result.UnmarshalJsonToObject(&resultService)
548         assert.NoError(t, err, "error unmarshaling response")
549         assert.Len(t, (*resultService.AefProfiles), 1)
550         assert.False(t, serviceUnderTest.IsAPIPublished("aefId", "path"))
551
552 }
553
554 func TestPublishInvalidService(t *testing.T) {
555         apfId := "apfId"
556         serviceRegisterMock := serviceMocks.ServiceRegister{}
557         serviceRegisterMock.On("IsPublishingFunctionRegistered", apfId).Return(true)
558
559         _, _, requestHandler := getEcho(&serviceRegisterMock, nil)
560         newServiceDescription := getServiceAPIDescription("aefId", " ", "description")
561
562         // Publish a service
563         result := testutil.NewRequest().Post("/apfId/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
564
565         assert.Equal(t, http.StatusBadRequest, result.Code())
566         var resultError common29122.ProblemDetails
567         err := result.UnmarshalJsonToObject(&resultError)
568         assert.NoError(t, err, "error unmarshaling response")
569         assert.Contains(t, *resultError.Cause, "missing")
570         assert.Contains(t, *resultError.Cause, "apiName")
571         assert.Equal(t, http.StatusBadRequest, *resultError.Status)
572
573 }
574 func getEcho(serviceRegister providermanagement.ServiceRegister, helmManager helmmanagement.HelmManager) (*PublishService, chan eventsapi.EventNotification, *echo.Echo) {
575         swagger, err := publishapi.GetSwagger()
576         if err != nil {
577                 fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
578                 os.Exit(1)
579         }
580
581         swagger.Servers = nil
582
583         eventChannel := make(chan eventsapi.EventNotification)
584         ps := NewPublishService(serviceRegister, helmManager, eventChannel)
585
586         e := echo.New()
587         e.Use(echomiddleware.Logger())
588         e.Use(middleware.OapiRequestValidator(swagger))
589
590         publishapi.RegisterHandlers(e, ps)
591         return ps, eventChannel, e
592 }
593
594 func getServiceAPIDescription(aefId, apiName, description string) publishapi.ServiceAPIDescription {
595         domainName := "domainName"
596         var protocol publishapi.Protocol = "HTTP_1_1"
597         return publishapi.ServiceAPIDescription{
598                 AefProfiles: &[]publishapi.AefProfile{
599                         {
600                                 AefId:      aefId,
601                                 DomainName: &domainName,
602                                 Protocol:   &protocol,
603                                 Versions: []publishapi.Version{
604                                         {
605                                                 ApiVersion: "v1",
606                                                 Resources: &[]publishapi.Resource{
607                                                         {
608                                                                 CommType: "REQUEST_RESPONSE",
609                                                                 Operations: &[]publishapi.Operation{
610                                                                         "POST",
611                                                                 },
612                                                                 ResourceName: "app",
613                                                                 Uri:          "app",
614                                                         },
615                                                 },
616                                         },
617                                 },
618                         },
619                 },
620                 ApiName:     apiName,
621                 Description: &description,
622         }
623 }
624
625 // waitForEvent waits for the channel to receive an event for the specified max timeout.
626 // Returns true if waiting timed out.
627 func waitForEvent(ch chan eventsapi.EventNotification, timeout time.Duration) (*eventsapi.EventNotification, bool) {
628         select {
629         case event := <-ch:
630                 return &event, false // completed normally
631         case <-time.After(timeout):
632                 return nil, true // timed out
633         }
634 }