2 // ========================LICENSE_START=================================
5 // Copyright (C) 2022: Nordix Foundation
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 // ========================LICENSE_END===================================
35 "github.com/deepmap/oapi-codegen/pkg/middleware"
36 "github.com/deepmap/oapi-codegen/pkg/testutil"
37 "github.com/labstack/echo/v4"
38 echomiddleware "github.com/labstack/echo/v4/middleware"
39 "github.com/stretchr/testify/assert"
40 "oransc.org/nonrtric/capifcore/internal/common29122"
41 "oransc.org/nonrtric/capifcore/internal/eventsapi"
42 "oransc.org/nonrtric/capifcore/internal/restclient"
45 func TestRegisterSubscriptions(t *testing.T) {
46 subscription1 := eventsapi.EventSubscription{
47 Events: []eventsapi.CAPIFEvent{
48 eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
50 NotificationDestination: common29122.Uri("notificationUrl"),
52 serviceUnderTest, requestHandler := getEcho(nil)
53 subscriberId := "subscriberId"
55 result := testutil.NewRequest().Post("/"+subscriberId+"/subscriptions").WithJsonBody(subscription1).Go(t, requestHandler)
56 assert.Equal(t, http.StatusCreated, result.Code())
57 var resultEvent eventsapi.EventSubscription
58 err := result.UnmarshalBodyToObject(&resultEvent)
59 assert.NoError(t, err, "error unmarshaling response")
60 assert.Equal(t, resultEvent, subscription1)
61 assert.Regexp(t, "http://example.com/"+subscriberId+"/subscriptions/"+subscriberId+"[0-9]+", result.Recorder.Header().Get(echo.HeaderLocation))
62 subscriptionId1 := path.Base(result.Recorder.Header().Get(echo.HeaderLocation))
64 subscription2 := subscription1
65 subscription2.Events = []eventsapi.CAPIFEvent{
66 eventsapi.CAPIFEventAPIINVOKERUPDATED,
68 result = testutil.NewRequest().Post("/"+subscriberId+"/subscriptions").WithJsonBody(subscription2).Go(t, requestHandler)
69 assert.Regexp(t, "http://example.com/"+subscriberId+"/subscriptions/"+subscriberId+"[0-9]+", result.Recorder.Header().Get(echo.HeaderLocation))
70 subscriptionId2 := path.Base(result.Recorder.Header().Get(echo.HeaderLocation))
72 assert.NotEqual(t, subscriptionId1, subscriptionId2)
73 registeredSub1 := serviceUnderTest.getSubscription(subscriptionId1)
74 assert.Equal(t, subscription1, *registeredSub1)
75 registeredSub2 := serviceUnderTest.getSubscription(subscriptionId2)
76 assert.Equal(t, subscription2, *registeredSub2)
79 func TestDeregisterSubscription(t *testing.T) {
80 subscription := eventsapi.EventSubscription{
81 Events: []eventsapi.CAPIFEvent{
82 eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
84 NotificationDestination: common29122.Uri(""),
86 serviceUnderTest, requestHandler := getEcho(nil)
88 serviceUnderTest.addSubscription(subId, subscription)
90 result := testutil.NewRequest().Delete("/subscriberId/subscriptions/"+subId).Go(t, requestHandler)
91 assert.Equal(t, http.StatusNoContent, result.Code())
92 assert.Nil(t, serviceUnderTest.getSubscription(subId))
95 func TestSendEvent(t *testing.T) {
96 notificationUrl := "url"
97 apiIds := []string{"apiId"}
99 newEvent := eventsapi.EventNotification{
100 EventDetail: &eventsapi.CAPIFEventDetail{
103 Events: eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
105 wg := sync.WaitGroup{}
106 clientMock := NewTestClient(func(req *http.Request) *http.Response {
107 if req.URL.String() == notificationUrl {
108 assert.Equal(t, req.Method, "PUT")
109 assert.Equal(t, "application/json", req.Header.Get("Content-Type"))
110 newEvent.SubscriptionId = subId
111 assert.Equal(t, newEvent, getBodyAsEvent(req, t))
113 return &http.Response{
115 Body: ioutil.NopCloser(bytes.NewBufferString(`OK`)),
116 Header: make(http.Header), // Must be set to non-nil value or it panics
119 t.Error("Wrong call to client: ", req)
123 serviceUnderTest, _ := getEcho(clientMock)
125 serviceUnderTest.addSubscription(subId, eventsapi.EventSubscription{
126 Events: []eventsapi.CAPIFEvent{
127 eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
129 NotificationDestination: common29122.Uri(notificationUrl),
131 sub2 := eventsapi.EventSubscription{
132 Events: []eventsapi.CAPIFEvent{
133 eventsapi.CAPIFEventACCESSCONTROLPOLICYUNAVAILABLE,
135 NotificationDestination: common29122.Uri(notificationUrl),
137 serviceUnderTest.addSubscription("other", sub2)
141 serviceUnderTest.GetNotificationChannel() <- newEvent
144 if waitTimeout(&wg, 1*time.Second) {
145 t.Error("Not all calls to server were made")
150 func TestMatchEventType(t *testing.T) {
151 notificationUrl := "url"
153 serviceUnderTest := NewEventService(nil)
154 serviceUnderTest.addSubscription(subId, eventsapi.EventSubscription{
155 Events: []eventsapi.CAPIFEvent{
156 eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
158 NotificationDestination: common29122.Uri(notificationUrl),
159 EventFilters: &[]eventsapi.CAPIFEventFilter{},
161 serviceUnderTest.addSubscription("other", eventsapi.EventSubscription{
162 Events: []eventsapi.CAPIFEvent{
163 eventsapi.CAPIFEventACCESSCONTROLPOLICYUNAVAILABLE,
165 NotificationDestination: common29122.Uri(notificationUrl),
168 event := eventsapi.EventNotification{
169 SubscriptionId: subId,
170 Events: eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
173 matchingSubs := serviceUnderTest.filterOnEventType(event)
174 assert.Len(t, matchingSubs, 1)
175 assert.Equal(t, subId, matchingSubs[0])
178 func TestMatchEventTypeAndFilters(t *testing.T) {
179 notificationUrl := "url"
181 apiIds := []string{"apiId"}
182 invokerIds := []string{"invokerId"}
183 serviceUnderTest := NewEventService(nil)
184 serviceUnderTest.addSubscription(subId, eventsapi.EventSubscription{
185 Events: []eventsapi.CAPIFEvent{
186 eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
188 NotificationDestination: common29122.Uri(notificationUrl),
189 EventFilters: &[]eventsapi.CAPIFEventFilter{
192 ApiInvokerIds: &invokerIds,
196 serviceUnderTest.addSubscription("other", eventsapi.EventSubscription{
197 Events: []eventsapi.CAPIFEvent{
198 eventsapi.CAPIFEventACCESSCONTROLPOLICYUNAVAILABLE,
200 NotificationDestination: common29122.Uri(notificationUrl),
203 event := eventsapi.EventNotification{
204 Events: eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
205 EventDetail: &eventsapi.CAPIFEventDetail{
207 ApiInvokerIds: &invokerIds,
211 matchingSubs := serviceUnderTest.getMatchingSubs(event)
212 assert.Len(t, matchingSubs, 1)
213 assert.Equal(t, subId, matchingSubs[0])
215 otherApiIds := []string{"otherApiId"}
216 (*serviceUnderTest.subscriptions[subId].EventFilters)[0].ApiIds = &otherApiIds
217 matchingSubs = serviceUnderTest.getMatchingSubs(event)
218 assert.Len(t, matchingSubs, 0)
220 otherInvokerIds := []string{"otherInvokerId"}
221 (*serviceUnderTest.subscriptions[subId].EventFilters)[0].ApiIds = &apiIds
222 (*serviceUnderTest.subscriptions[subId].EventFilters)[0].ApiInvokerIds = &otherInvokerIds
223 matchingSubs = serviceUnderTest.getMatchingSubs(event)
224 assert.Len(t, matchingSubs, 0)
227 func getEcho(client restclient.HTTPClient) (*EventService, *echo.Echo) {
228 swagger, err := eventsapi.GetSwagger()
230 fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
234 swagger.Servers = nil
236 es := NewEventService(client)
239 e.Use(echomiddleware.Logger())
240 e.Use(middleware.OapiRequestValidator(swagger))
242 eventsapi.RegisterHandlers(e, es)
246 type RoundTripFunc func(req *http.Request) *http.Response
248 func (f RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
252 // NewTestClient returns *http.Client with Transport replaced to avoid making real calls
253 func NewTestClient(fn RoundTripFunc) *http.Client {
255 Transport: RoundTripFunc(fn),
259 // waitTimeout waits for the waitgroup for the specified max timeout.
260 // Returns true if waiting timed out.
261 func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
262 c := make(chan struct{})
269 return false // completed normally
270 case <-time.After(timeout):
271 return true // timed out
275 func getBodyAsEvent(req *http.Request, t *testing.T) eventsapi.EventNotification {
276 buf := new(bytes.Buffer)
277 if _, err := buf.ReadFrom(req.Body); err != nil {
280 var event eventsapi.EventNotification
281 err := json.Unmarshal(buf.Bytes(), &event)