3 // ========================LICENSE_START=================================
6 // Copyright (C) 2022: Nordix Foundation
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
12 // http://www.apache.org/licenses/LICENSE-2.0
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
29 "oransc.org/nonrtric/capifcore/internal/invokermanagementapi"
31 "github.com/labstack/echo/v4"
33 "oransc.org/nonrtric/capifcore/internal/common29122"
34 "oransc.org/nonrtric/capifcore/internal/publishserviceapi"
36 "oransc.org/nonrtric/capifcore/internal/publishservice"
37 publishmocks "oransc.org/nonrtric/capifcore/internal/publishservice/mocks"
39 "github.com/deepmap/oapi-codegen/pkg/middleware"
40 "github.com/deepmap/oapi-codegen/pkg/testutil"
41 echomiddleware "github.com/labstack/echo/v4/middleware"
42 "github.com/stretchr/testify/assert"
43 "github.com/stretchr/testify/mock"
46 func TestOnboardInvoker(t *testing.T) {
47 publishRegisterMock := publishmocks.PublishRegister{}
48 publishRegisterMock.On("AreAPIsPublished", mock.Anything).Return(true)
49 invokerUnderTest, requestHandler := getEcho(&publishRegisterMock)
51 aefProfiles := []publishserviceapi.AefProfile{
52 getAefProfile("aefId"),
55 var apiList invokermanagementapi.APIList = []publishserviceapi.ServiceAPIDescription{
58 AefProfiles: &aefProfiles,
61 newInvoker := getInvoker("invoker a", apiList)
63 // Onboard a valid invoker
64 result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
66 assert.Equal(t, http.StatusCreated, result.Code())
67 var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails
68 err := result.UnmarshalBodyToObject(&resultInvoker)
69 assert.NoError(t, err, "error unmarshaling response")
70 assert.Equal(t, "api_invoker_id_invoker_a", *resultInvoker.ApiInvokerId)
71 assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination)
72 assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey)
73 assert.Equal(t, "onboarding_secret_invoker_a", *resultInvoker.OnboardingInformation.OnboardingSecret)
74 assert.Equal(t, "http://example.com/onboardedInvokers/"+*resultInvoker.ApiInvokerId, result.Recorder.Header().Get(echo.HeaderLocation))
75 assert.True(t, invokerUnderTest.IsInvokerRegistered("api_invoker_id_invoker_a"))
76 assert.True(t, invokerUnderTest.VerifyInvokerSecret("api_invoker_id_invoker_a", "onboarding_secret_invoker_a"))
77 publishRegisterMock.AssertCalled(t, "AreAPIsPublished", mock.Anything)
79 // Onboard an invoker missing required NotificationDestination, should get 400 with problem details
80 invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
81 OnboardingInformation: invokermanagementapi.OnboardingInformation{
82 ApiInvokerPublicKey: "key",
85 result = testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(invalidInvoker).Go(t, requestHandler)
87 assert.Equal(t, http.StatusBadRequest, result.Code())
88 var problemDetails common29122.ProblemDetails
89 err = result.UnmarshalBodyToObject(&problemDetails)
90 assert.NoError(t, err, "error unmarshaling response")
91 badRequest := http.StatusBadRequest
92 assert.Equal(t, &badRequest, problemDetails.Status)
93 errMsg := "Invoker missing required NotificationDestination"
94 assert.Equal(t, &errMsg, problemDetails.Cause)
96 // Onboard an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details
97 invalidInvoker = invokermanagementapi.APIInvokerEnrolmentDetails{
98 NotificationDestination: "url",
101 result = testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(invalidInvoker).Go(t, requestHandler)
103 assert.Equal(t, http.StatusBadRequest, result.Code())
104 err = result.UnmarshalBodyToObject(&problemDetails)
105 assert.NoError(t, err, "error unmarshaling response")
106 assert.Equal(t, &badRequest, problemDetails.Status)
107 errMsg = "Invoker missing required OnboardingInformation.ApiInvokerPublicKey"
108 assert.Equal(t, &errMsg, problemDetails.Cause)
111 func TestDeleteInvoker(t *testing.T) {
112 invokerUnderTest, requestHandler := getEcho(nil)
114 newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
115 NotificationDestination: "url",
116 OnboardingInformation: invokermanagementapi.OnboardingInformation{
117 ApiInvokerPublicKey: "key",
121 // Onboard an invoker
122 result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
124 invokerUrl := result.Recorder.Header().Get(echo.HeaderLocation)
125 assert.True(t, invokerUnderTest.IsInvokerRegistered(path.Base(invokerUrl)))
127 // Delete the invoker
128 result = testutil.NewRequest().Delete(invokerUrl).Go(t, requestHandler)
130 assert.Equal(t, http.StatusNoContent, result.Code())
131 assert.False(t, invokerUnderTest.IsInvokerRegistered(path.Base(invokerUrl)))
134 func TestUpdateInvoker(t *testing.T) {
135 _, requestHandler := getEcho(nil)
137 newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
138 NotificationDestination: "url",
139 OnboardingInformation: invokermanagementapi.OnboardingInformation{
140 ApiInvokerPublicKey: "key",
144 // Onboard an invoker
145 result := testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
146 var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails
147 result.UnmarshalBodyToObject(&resultInvoker)
149 invokerId := resultInvoker.ApiInvokerId
150 invokerUrl := result.Recorder.Header().Get(echo.HeaderLocation)
152 // Update the invoker with valid invoker, should return 200 with invoker details
153 result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(resultInvoker).Go(t, requestHandler)
155 assert.Equal(t, http.StatusOK, result.Code())
156 err := result.UnmarshalBodyToObject(&resultInvoker)
157 assert.NoError(t, err, "error unmarshaling response")
158 assert.Equal(t, invokerId, resultInvoker.ApiInvokerId)
159 assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination)
160 assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey)
162 // Update with an invoker missing required NotificationDestination, should get 400 with problem details
163 validOnboardingInfo := invokermanagementapi.OnboardingInformation{
164 ApiInvokerPublicKey: "key",
166 invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
167 ApiInvokerId: invokerId,
168 OnboardingInformation: validOnboardingInfo,
170 result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler)
172 assert.Equal(t, http.StatusBadRequest, result.Code())
173 var problemDetails common29122.ProblemDetails
174 err = result.UnmarshalBodyToObject(&problemDetails)
175 assert.NoError(t, err, "error unmarshaling response")
176 badRequest := http.StatusBadRequest
177 assert.Equal(t, &badRequest, problemDetails.Status)
178 errMsg := "Invoker missing required NotificationDestination"
179 assert.Equal(t, &errMsg, problemDetails.Cause)
181 // Update with an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details
182 invalidInvoker.NotificationDestination = "url"
183 invalidInvoker.OnboardingInformation = invokermanagementapi.OnboardingInformation{}
184 result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler)
186 assert.Equal(t, http.StatusBadRequest, result.Code())
187 err = result.UnmarshalBodyToObject(&problemDetails)
188 assert.NoError(t, err, "error unmarshaling response")
189 assert.Equal(t, &badRequest, problemDetails.Status)
190 errMsg = "Invoker missing required OnboardingInformation.ApiInvokerPublicKey"
191 assert.Equal(t, &errMsg, problemDetails.Cause)
193 // Update with an invoker with other ApiInvokerId than the one provided in the URL, should get 400 with problem details
195 invalidInvoker.ApiInvokerId = &invalidId
196 invalidInvoker.OnboardingInformation = validOnboardingInfo
197 result = testutil.NewRequest().Put(invokerUrl).WithJsonBody(invalidInvoker).Go(t, requestHandler)
199 assert.Equal(t, http.StatusBadRequest, result.Code())
200 err = result.UnmarshalBodyToObject(&problemDetails)
201 assert.NoError(t, err, "error unmarshaling response")
202 assert.Equal(t, &badRequest, problemDetails.Status)
203 errMsg = "Invoker ApiInvokerId not matching"
204 assert.Equal(t, &errMsg, problemDetails.Cause)
206 // Update an invoker that has not been onboarded, shold get 404 with problem details
208 newInvoker.ApiInvokerId = &missingId
209 result = testutil.NewRequest().Put("/onboardedInvokers/"+missingId).WithJsonBody(newInvoker).Go(t, requestHandler)
211 assert.Equal(t, http.StatusNotFound, result.Code())
212 err = result.UnmarshalBodyToObject(&problemDetails)
213 assert.NoError(t, err, "error unmarshaling response")
214 notFound := http.StatusNotFound
215 assert.Equal(t, ¬Found, problemDetails.Status)
216 errMsg = "The invoker to update has not been onboarded"
217 assert.Equal(t, &errMsg, problemDetails.Cause)
220 func TestGetInvokerApiList(t *testing.T) {
221 publishRegisterMock := publishmocks.PublishRegister{}
222 publishRegisterMock.On("AreAPIsPublished", mock.Anything).Return(true)
223 invokerUnderTest, requestHandler := getEcho(&publishRegisterMock)
225 // Onboard two invokers
226 aefProfiles := []publishserviceapi.AefProfile{
227 getAefProfile("aefId"),
230 var apiList invokermanagementapi.APIList = []publishserviceapi.ServiceAPIDescription{
233 AefProfiles: &aefProfiles,
236 newInvoker := getInvoker("invoker a", apiList)
237 testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
238 aefProfiles = []publishserviceapi.AefProfile{
239 getAefProfile("aefId2"),
242 apiList = []publishserviceapi.ServiceAPIDescription{
245 AefProfiles: &aefProfiles,
248 newInvoker = getInvoker("invoker b", apiList)
249 testutil.NewRequest().Post("/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
251 wantedApiList := invokerUnderTest.GetInvokerApiList("api_invoker_id_invoker_a")
252 assert.NotNil(t, wantedApiList)
253 assert.Equal(t, apiId, *(*wantedApiList)[0].ApiId)
256 func getEcho(publishRegister publishservice.PublishRegister) (*InvokerManager, *echo.Echo) {
257 swagger, err := invokermanagementapi.GetSwagger()
259 fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
263 swagger.Servers = nil
265 im := NewInvokerManager(publishRegister)
268 e.Use(echomiddleware.Logger())
269 e.Use(middleware.OapiRequestValidator(swagger))
271 invokermanagementapi.RegisterHandlers(e, im)
275 func getAefProfile(aefId string) publishserviceapi.AefProfile {
276 return publishserviceapi.AefProfile{
278 Versions: []publishserviceapi.Version{
280 Resources: &[]publishserviceapi.Resource{
282 CommType: "REQUEST_RESPONSE",
290 func getInvoker(invokerInfo string, apiList invokermanagementapi.APIList) invokermanagementapi.APIInvokerEnrolmentDetails {
291 newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
292 ApiInvokerInformation: &invokerInfo,
293 NotificationDestination: "url",
294 OnboardingInformation: invokermanagementapi.OnboardingInformation{
295 ApiInvokerPublicKey: "key",