--- /dev/null
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2023: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+
+package eventsapi
+
+import (
+ "errors"
+ "fmt"
+ "net/url"
+ "strings"
+)
+
+func (es EventSubscription) Validate() error {
+ if len(es.Events) == 0 {
+ return errors.New("required attribute EventSubscription:events must contain at least one element")
+ }
+
+ for _, event := range es.Events {
+ if err := validateEvent(event); err != nil {
+ return errors.New("EventSubscription events contains invalid event")
+ }
+ }
+
+ if len(strings.TrimSpace(string(es.NotificationDestination))) == 0 {
+ return errors.New("EventSubscription missing required notificationDestination")
+ }
+ if _, err := url.ParseRequestURI(string(es.NotificationDestination)); err != nil {
+ return fmt.Errorf("APIInvokerEnrolmentDetails has invalid notificationDestination, err=%s", err)
+ }
+
+ return nil
+}
+
+func validateEvent(event CAPIFEvent) error {
+ switch event {
+ case CAPIFEventACCESSCONTROLPOLICYUNAVAILABLE:
+ case CAPIFEventACCESSCONTROLPOLICYUPDATE:
+ case CAPIFEventAPIINVOKERAUTHORIZATIONREVOKED:
+ case CAPIFEventAPIINVOKEROFFBOARDED:
+ case CAPIFEventAPIINVOKERONBOARDED:
+ case CAPIFEventAPIINVOKERUPDATED:
+ case CAPIFEventAPITOPOLOGYHIDINGCREATED:
+ case CAPIFEventAPITOPOLOGYHIDINGREVOKED:
+ case CAPIFEventSERVICEAPIAVAILABLE:
+ case CAPIFEventSERVICEAPIINVOCATIONFAILURE:
+ case CAPIFEventSERVICEAPIINVOCATIONSUCCESS:
+ case CAPIFEventSERVICEAPIUNAVAILABLE:
+ case CAPIFEventSERVICEAPIUPDATE:
+ default:
+ return errors.New("wrong event type")
+ }
+ return nil
+}
--- /dev/null
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2023: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+
+package eventsapi
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestValidateEventSubscription(t *testing.T) {
+ subUnderTest := EventSubscription{}
+
+ err := subUnderTest.Validate()
+
+ assert.NotNil(t, err)
+ assert.Contains(t, err.Error(), "required")
+ assert.Contains(t, err.Error(), "events")
+
+ var invalidEventType CAPIFEvent = "invalid"
+ subUnderTest.Events = []CAPIFEvent{invalidEventType}
+ err = subUnderTest.Validate()
+ assert.NotNil(t, err)
+ assert.Contains(t, err.Error(), "invalid")
+ assert.Contains(t, err.Error(), "events")
+
+ subUnderTest.Events = []CAPIFEvent{CAPIFEventAPIINVOKERONBOARDED}
+ err = subUnderTest.Validate()
+ assert.NotNil(t, err)
+ assert.Contains(t, err.Error(), "missing")
+ assert.Contains(t, err.Error(), "notificationDestination")
+
+ subUnderTest.NotificationDestination = "invalid dest"
+ err = subUnderTest.Validate()
+ if assert.Error(t, err) {
+ assert.Contains(t, err.Error(), "invalid")
+ assert.Contains(t, err.Error(), "notificationDestination")
+ }
+
+ subUnderTest.NotificationDestination = "http://golang.cafe/"
+ err = subUnderTest.Validate()
+ assert.Nil(t, err)
+}
if err != nil {
return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
}
+
+ if err := newSubscription.Validate(); err != nil {
+ return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
+ }
+
uri := ctx.Request().Host + ctx.Request().URL.String()
subId := es.getSubscriptionId(subscriberId)
es.addSubscription(subId, newSubscription)
filterIds := getIds(filter)
if filterIds == nil || len(*filterIds) == 0 {
return matchesFilters(eventIds, filters[1:], getIds)
+ } else {
+ return slices.Contains(*getIds(filter), id) && matchesFilters(eventIds, filters[1:], getIds)
}
- return slices.Contains(*getIds(filter), id) && matchesFilters(eventIds, filters[1:], getIds)
}
return true
}
"bytes"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"os"
"path"
Events: []eventsapi.CAPIFEvent{
eventsapi.CAPIFEventSERVICEAPIAVAILABLE,
},
- NotificationDestination: common29122.Uri("notificationUrl"),
+ NotificationDestination: common29122.Uri("http://golang.cafe/"),
}
serviceUnderTest, requestHandler := getEcho(nil)
subscriberId := "subscriberId"
assert.Equal(t, subscription2, *registeredSub2)
}
+func TestRegisterInvalidSubscription(t *testing.T) {
+ subscription1 := eventsapi.EventSubscription{
+ Events: []eventsapi.CAPIFEvent{eventsapi.CAPIFEventACCESSCONTROLPOLICYUNAVAILABLE},
+ }
+ serviceUnderTest, requestHandler := getEcho(nil)
+ subscriberId := "subscriberId"
+
+ result := testutil.NewRequest().Post("/"+subscriberId+"/subscriptions").WithJsonBody(subscription1).Go(t, requestHandler)
+ assert.Equal(t, http.StatusBadRequest, result.Code())
+ var problemDetails common29122.ProblemDetails
+ err := result.UnmarshalBodyToObject(&problemDetails)
+ assert.NoError(t, err, "error unmarshaling response")
+ badRequest := http.StatusBadRequest
+ assert.Equal(t, &badRequest, problemDetails.Status)
+ assert.Contains(t, *problemDetails.Cause, "missing")
+ assert.Contains(t, *problemDetails.Cause, "notificationDestination")
+ subscriptionId := path.Base(result.Recorder.Header().Get(echo.HeaderLocation))
+ registeredSub := serviceUnderTest.getSubscription(subscriptionId)
+ assert.Nil(t, registeredSub)
+}
+
func TestDeregisterSubscription(t *testing.T) {
subscription := eventsapi.EventSubscription{
Events: []eventsapi.CAPIFEvent{
wg.Done()
return &http.Response{
StatusCode: 200,
- Body: ioutil.NopCloser(bytes.NewBufferString(`OK`)),
+ Body: io.NopCloser(bytes.NewBufferString(`OK`)),
Header: make(http.Header), // Must be set to non-nil value or it panics
}
}
}()
if waitTimeout(&wg, 1*time.Second) {
- t.Error("Not all calls to server were made")
+ t.Error("No event notification was sent")
t.Fail()
}
}