Move capifcore code to separate folder
[nonrtric/plt/sme.git] / capifcore / internal / invokermanagement / invokermanagement_test.go
1 // -
2 //
3 //      ========================LICENSE_START=================================
4 //      O-RAN-SC
5 //      %%
6 //      Copyright (C) 2022: Nordix Foundation
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 package invokermanagement
21
22 import (
23         "fmt"
24         "net/http"
25         "os"
26         "testing"
27
28         "oransc.org/nonrtric/capifcore/internal/invokermanagementapi"
29
30         "github.com/labstack/echo/v4"
31
32         "oransc.org/nonrtric/capifcore/internal/common29122"
33         "oransc.org/nonrtric/capifcore/internal/publishserviceapi"
34
35         "oransc.org/nonrtric/capifcore/internal/publishservice"
36         publishmocks "oransc.org/nonrtric/capifcore/internal/publishservice/mocks"
37
38         "github.com/deepmap/oapi-codegen/pkg/middleware"
39         "github.com/deepmap/oapi-codegen/pkg/testutil"
40         echomiddleware "github.com/labstack/echo/v4/middleware"
41         "github.com/stretchr/testify/assert"
42         "github.com/stretchr/testify/mock"
43 )
44
45 func TestOnboardInvoker(t *testing.T) {
46         var err error
47         apiId := "apiId"
48         aefId := "aefId"
49         apiRegisterMock := publishmocks.APIRegister{}
50         apiRegisterMock.On("AreAPIsRegistered", mock.Anything).Return(true)
51         invokerUnderTest, requestHandler := getEcho(&apiRegisterMock)
52
53         description := "description"
54         domainName := "domain"
55         var protocol publishserviceapi.Protocol = "HTTP_1_1"
56         var apiList invokermanagementapi.APIList = []publishserviceapi.ServiceAPIDescription{
57                 {
58                         ApiId:       &apiId,
59                         ApiName:     "api",
60                         Description: &description,
61                         AefProfiles: &[]publishserviceapi.AefProfile{
62                                 {
63                                         AefId:      aefId,
64                                         DomainName: &domainName,
65                                         Protocol:   &protocol,
66                                         Versions: []publishserviceapi.Version{
67                                                 {
68                                                         ApiVersion: "v1",
69                                                         Resources: &[]publishserviceapi.Resource{
70                                                                 {
71                                                                         ResourceName: "app",
72                                                                         CommType:     "REQUEST_RESPONSE",
73                                                                         Uri:          "uri",
74                                                                         Operations: &[]publishserviceapi.Operation{
75                                                                                 "POST",
76                                                                         },
77                                                                 },
78                                                         },
79                                                 },
80                                         },
81                                 },
82                         },
83                 },
84         }
85         invokerInfo := "invoker a"
86         newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
87                 ApiInvokerInformation:   &invokerInfo,
88                 NotificationDestination: "url",
89                 OnboardingInformation: invokermanagementapi.OnboardingInformation{
90                         ApiInvokerPublicKey: "key",
91                 },
92                 ApiList: &apiList,
93         }
94
95         // Onboard a valid invoker
96         result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
97
98         assert.Equal(t, http.StatusCreated, result.Code())
99         var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails
100         err = result.UnmarshalBodyToObject(&resultInvoker)
101         assert.NoError(t, err, "error unmarshaling response")
102         assert.Equal(t, "api_invoker_id_invoker_a", *resultInvoker.ApiInvokerId)
103         assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination)
104         assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey)
105         assert.Equal(t, "onboarding_secret_invoker_a", *resultInvoker.OnboardingInformation.OnboardingSecret)
106         assert.Equal(t, "http://example.com/onboardedInvokers/"+*resultInvoker.ApiInvokerId, result.Recorder.Header().Get(echo.HeaderLocation))
107         assert.True(t, invokerUnderTest.IsInvokerRegistered("api_invoker_id_invoker_a"))
108         assert.True(t, invokerUnderTest.VerifyInvokerSecret("api_invoker_id_invoker_a", "onboarding_secret_invoker_a"))
109         apiRegisterMock.AssertCalled(t, "AreAPIsRegistered", mock.Anything)
110
111         // Onboard an invoker missing required NotificationDestination, should get 400 with problem details
112         invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
113                 OnboardingInformation: invokermanagementapi.OnboardingInformation{
114                         ApiInvokerPublicKey: "key",
115                 },
116         }
117         result = testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(invalidInvoker).Go(t, requestHandler)
118
119         assert.Equal(t, http.StatusBadRequest, result.Code())
120         var problemDetails common29122.ProblemDetails
121         err = result.UnmarshalBodyToObject(&problemDetails)
122         assert.NoError(t, err, "error unmarshaling response")
123         badRequest := 400
124         assert.Equal(t, &badRequest, problemDetails.Status)
125         errMsg := "Invoker missing required NotificationDestination"
126         assert.Equal(t, &errMsg, problemDetails.Cause)
127
128         // Onboard an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details
129         invalidInvoker = invokermanagementapi.APIInvokerEnrolmentDetails{
130                 NotificationDestination: "url",
131         }
132
133         result = testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(invalidInvoker).Go(t, requestHandler)
134
135         assert.Equal(t, http.StatusBadRequest, result.Code())
136         err = result.UnmarshalBodyToObject(&problemDetails)
137         assert.NoError(t, err, "error unmarshaling response")
138         assert.Equal(t, &badRequest, problemDetails.Status)
139         errMsg = "Invoker missing required OnboardingInformation.ApiInvokerPublicKey"
140         assert.Equal(t, &errMsg, problemDetails.Cause)
141 }
142
143 func TestDeleteInvoker(t *testing.T) {
144         _, requestHandler := getEcho(nil)
145
146         newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
147                 NotificationDestination: "url",
148                 OnboardingInformation: invokermanagementapi.OnboardingInformation{
149                         ApiInvokerPublicKey: "key",
150                 },
151         }
152
153         // Onboard an invoker
154         result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
155         var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails
156         result.UnmarshalBodyToObject(&resultInvoker)
157
158         invokerUrl := result.Recorder.Header().Get(echo.HeaderLocation)
159
160         // Delete the invoker
161         result = testutil.NewRequest().Delete(invokerUrl).Go(t, requestHandler)
162
163         assert.Equal(t, http.StatusNoContent, result.Code())
164 }
165
166 func TestUpdateInvoker(t *testing.T) {
167         _, requestHandler := getEcho(nil)
168
169         newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
170                 NotificationDestination: "url",
171                 OnboardingInformation: invokermanagementapi.OnboardingInformation{
172                         ApiInvokerPublicKey: "key",
173                 },
174         }
175
176         // Onboard an invoker
177         result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
178         var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails
179         result.UnmarshalBodyToObject(&resultInvoker)
180
181         invokerId := resultInvoker.ApiInvokerId
182         invokerUrl := result.Recorder.Header().Get(echo.HeaderLocation)
183
184         // Update the invoker with valid invoker, should return 200 with invoker details
185         result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(resultInvoker).Go(t, requestHandler)
186
187         assert.Equal(t, http.StatusOK, result.Code())
188         err := result.UnmarshalBodyToObject(&resultInvoker)
189         assert.NoError(t, err, "error unmarshaling response")
190         assert.Equal(t, invokerId, resultInvoker.ApiInvokerId)
191         assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination)
192         assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey)
193
194         // Update with an invoker missing required NotificationDestination, should get 400 with problem details
195         validOnboardingInfo := invokermanagementapi.OnboardingInformation{
196                 ApiInvokerPublicKey: "key",
197         }
198         invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
199                 ApiInvokerId:          invokerId,
200                 OnboardingInformation: validOnboardingInfo,
201         }
202         result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler)
203
204         assert.Equal(t, http.StatusBadRequest, result.Code())
205         var problemDetails common29122.ProblemDetails
206         err = result.UnmarshalBodyToObject(&problemDetails)
207         assert.NoError(t, err, "error unmarshaling response")
208         badRequest := 400
209         assert.Equal(t, &badRequest, problemDetails.Status)
210         errMsg := "Invoker missing required NotificationDestination"
211         assert.Equal(t, &errMsg, problemDetails.Cause)
212
213         // Update with an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details
214         invalidInvoker.NotificationDestination = "url"
215         invalidInvoker.OnboardingInformation = invokermanagementapi.OnboardingInformation{}
216         result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler)
217
218         assert.Equal(t, http.StatusBadRequest, result.Code())
219         err = result.UnmarshalBodyToObject(&problemDetails)
220         assert.NoError(t, err, "error unmarshaling response")
221         assert.Equal(t, &badRequest, problemDetails.Status)
222         errMsg = "Invoker missing required OnboardingInformation.ApiInvokerPublicKey"
223         assert.Equal(t, &errMsg, problemDetails.Cause)
224
225         // Update with an invoker with other ApiInvokerId than the one provided in the URL, should get 400 with problem details
226         invalidId := "1"
227         invalidInvoker.ApiInvokerId = &invalidId
228         invalidInvoker.OnboardingInformation = validOnboardingInfo
229         result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler)
230
231         assert.Equal(t, http.StatusBadRequest, result.Code())
232         err = result.UnmarshalBodyToObject(&problemDetails)
233         assert.NoError(t, err, "error unmarshaling response")
234         assert.Equal(t, &badRequest, problemDetails.Status)
235         errMsg = "Invoker ApiInvokerId not matching"
236         assert.Equal(t, &errMsg, problemDetails.Cause)
237
238         // Update an invoker that has not been onboarded, shold get 404 with problem details
239         missingId := "1"
240         newInvoker.ApiInvokerId = &missingId
241         result = testutil.NewRequest().Put("/onboardedInvokers/"+missingId).WithJsonBody(newInvoker).Go(t, requestHandler)
242
243         assert.Equal(t, http.StatusNotFound, result.Code())
244         err = result.UnmarshalBodyToObject(&problemDetails)
245         assert.NoError(t, err, "error unmarshaling response")
246         notFound := 404
247         assert.Equal(t, &notFound, problemDetails.Status)
248         errMsg = "The invoker to update has not been onboarded"
249         assert.Equal(t, &errMsg, problemDetails.Cause)
250
251 }
252
253 func getEcho(apiRegister publishservice.APIRegister) (*InvokerManager, *echo.Echo) {
254         swagger, err := invokermanagementapi.GetSwagger()
255         if err != nil {
256                 fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
257                 os.Exit(1)
258         }
259
260         swagger.Servers = nil
261
262         im := NewInvokerManager(apiRegister)
263
264         e := echo.New()
265         e.Use(echomiddleware.Logger())
266         e.Use(middleware.OapiRequestValidator(swagger))
267
268         invokermanagementapi.RegisterHandlers(e, im)
269         return im, e
270 }