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 subscription := eventsapi.EventSubscription{
126 Events: []eventsapi.CAPIFEvent{
127 eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
129 NotificationDestination: common29122.Uri(notificationUrl),
131 serviceUnderTest.addSubscription(subId, subscription)
132 sub2 := eventsapi.EventSubscription{
133 Events: []eventsapi.CAPIFEvent{
134 eventsapi.CAPIFEventACCESSCONTROLPOLICYUNAVAILABLE,
136 NotificationDestination: common29122.Uri(notificationUrl),
138 serviceUnderTest.addSubscription("other", sub2)
142 serviceUnderTest.GetNotificationChannel() <- newEvent
145 if waitTimeout(&wg, 1*time.Second) {
146 t.Error("Not all calls to server were made")
151 func TestMatchEventType(t *testing.T) {
152 notificationUrl := "url"
154 serviceUnderTest := NewEventService(nil)
155 subscription := eventsapi.EventSubscription{
156 Events: []eventsapi.CAPIFEvent{
157 eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
159 NotificationDestination: common29122.Uri(notificationUrl),
161 serviceUnderTest.addSubscription(subId, subscription)
162 sub2 := eventsapi.EventSubscription{
163 Events: []eventsapi.CAPIFEvent{
164 eventsapi.CAPIFEventACCESSCONTROLPOLICYUNAVAILABLE,
166 NotificationDestination: common29122.Uri(notificationUrl),
168 serviceUnderTest.addSubscription("other", sub2)
170 event := eventsapi.EventNotification{
171 SubscriptionId: subId,
172 Events: eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
175 matchingSubs := serviceUnderTest.getMatchingSubs(event)
176 assert.Len(t, matchingSubs, 1)
177 assert.Equal(t, subId, matchingSubs[0])
180 func getEcho(client restclient.HTTPClient) (*EventService, *echo.Echo) {
181 swagger, err := eventsapi.GetSwagger()
183 fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
187 swagger.Servers = nil
189 es := NewEventService(client)
192 e.Use(echomiddleware.Logger())
193 e.Use(middleware.OapiRequestValidator(swagger))
195 eventsapi.RegisterHandlers(e, es)
199 type RoundTripFunc func(req *http.Request) *http.Response
201 func (f RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
205 // NewTestClient returns *http.Client with Transport replaced to avoid making real calls
206 func NewTestClient(fn RoundTripFunc) *http.Client {
208 Transport: RoundTripFunc(fn),
212 // waitTimeout waits for the waitgroup for the specified max timeout.
213 // Returns true if waiting timed out.
214 func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
215 c := make(chan struct{})
222 return false // completed normally
223 case <-time.After(timeout):
224 return true // timed out
228 func getBodyAsEvent(req *http.Request, t *testing.T) eventsapi.EventNotification {
229 buf := new(bytes.Buffer)
230 if _, err := buf.ReadFrom(req.Body); err != nil {
233 var event eventsapi.EventNotification
234 err := json.Unmarshal(buf.Bytes(), &event)