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