From 268d715e3bceab8f7955d89945141efdb2c3b368 Mon Sep 17 00:00:00 2001 From: Konstantinos Archangelof Date: Mon, 14 Jun 2021 12:24:00 +0300 Subject: [PATCH] Submgr REST subscriptions in SDL Database * renamed sdl.go to sdl_e2SubsDb.go * renamed sdl_test.go to sdl_e2SubsDb_test.go * New file sdl_restSubsDb.go implements the SDL API for the REST Subscriptions * New file sdl_restSubsDb_test.go implements unittests for the SDL API for the REST Subscriptions * New db restSubsDb defined under Control object in submgr to hold the SDL DB data structure * SDL API for the REST Subscriptions is called from submgr code. Signed-off-by: Konstantinos Archangelof Change-Id: I447da9030aba2a582e38d24ef86722894d0c41e1 --- pkg/control/control.go | 58 ++- pkg/control/registry.go | 4 +- pkg/control/{sdl.go => sdl_e2SubsDb.go} | 29 +- pkg/control/{sdl_test.go => sdl_e2SubsDb_test.go} | 16 +- pkg/control/sdl_restSubsDb.go | 174 ++++++++ pkg/control/sdl_restSubsDb_test.go | 486 ++++++++++++++++++++++ pkg/control/ut_ctrl_submgr_test.go | 3 +- 7 files changed, 741 insertions(+), 29 deletions(-) rename pkg/control/{sdl.go => sdl_e2SubsDb.go} (88%) rename pkg/control/{sdl_test.go => sdl_e2SubsDb_test.go} (98%) create mode 100644 pkg/control/sdl_restSubsDb.go create mode 100644 pkg/control/sdl_restSubsDb_test.go diff --git a/pkg/control/control.go b/pkg/control/control.go index 9779498..c74b1a5 100755 --- a/pkg/control/control.go +++ b/pkg/control/control.go @@ -74,7 +74,8 @@ type Control struct { e2ap *E2ap registry *Registry tracker *Tracker - db Sdlnterface + e2SubsDb Sdlnterface + restSubsDb Sdlnterface CntRecvMsg uint64 ResetTestFlag bool Counters map[string]xapp.Counter @@ -112,7 +113,8 @@ func NewControl() *Control { c := &Control{e2ap: new(E2ap), registry: registry, tracker: tracker, - db: CreateSdl(), + e2SubsDb: CreateSdl(), + restSubsDb: CreateRESTSdl(), Counters: xapp.Metric.RegisterCounterGroup(GetMetricsOpts(), "SUBMGR"), LoggerLevel: 3, } @@ -140,6 +142,13 @@ func NewControl() *Control { c.registry.register = register c.HandleUncompletedSubscriptions(register) } + + restSubscriptions, err := c.ReadAllRESTSubscriptionsFromSdl() + if err != nil { + xapp.Logger.Error("%v", err) + } else { + c.registry.restSubscriptions = restSubscriptions + } return c } @@ -299,9 +308,11 @@ func (c *Control) SubscriptionHandler(params interface{}) (*models.SubscriptionR return &subResp, nil } } - restSubscription.Md5sumOngoing = md5sum + restSubscription.Md5sum = md5sum } + c.WriteRESTSubscriptionToDb(restSubId, restSubscription) + go c.processSubscriptionRequests(restSubscription, &subReqList, p.ClientEndpoint, p.Meid, &restSubId, xAppRmrEndpoint) c.UpdateCounter(cRestSubRespToXapp) @@ -324,6 +335,7 @@ func (c *Control) sendUnsuccesfullResponseNotification(restSubId *string, restSu } // Mark REST subscription request processed. restSubscription.SetProcessed() + c.UpdateRESTSubscriptionInDB(*restSubId, restSubscription, false) if trans != nil { xapp.Logger.Info("Sending unsuccessful REST notification (cause %s) to endpoint=%v:%v, XappEventInstanceID=%v, E2EventInstanceID=%v, %s", errorCause, clientEndpoint.Host, *clientEndpoint.HTTPPort, xAppEventInstanceID, e2EventInstanceID, idstring(nil, trans)) @@ -354,6 +366,7 @@ func (c *Control) sendSuccesfullResponseNotification(restSubId *string, restSubs } // Mark REST subscription request processesd. restSubscription.SetProcessed() + c.UpdateRESTSubscriptionInDB(*restSubId, restSubscription, false) xapp.Logger.Info("Sending successful REST notification to endpoint=%v:%v, XappEventInstanceID=%v, E2EventInstanceID=%v, %s", clientEndpoint.Host, *clientEndpoint.HTTPPort, xAppEventInstanceID, e2EventInstanceID, idstring(nil, trans)) @@ -373,7 +386,7 @@ func (c *Control) processSubscriptionRequests(restSubscription *RESTSubscription var xAppEventInstanceID int64 var e2EventInstanceID int64 - defer restDuplicateCtrl.TransactionComplete(restSubscription.Md5sumOngoing) + defer restDuplicateCtrl.TransactionComplete(restSubscription.Md5sum) for index := 0; index < len(subReqList.E2APSubscriptionRequests); index++ { subReqMsg := subReqList.E2APSubscriptionRequests[index] @@ -491,6 +504,7 @@ func (c *Control) SubscriptionDeleteHandlerCB(restSubId string) error { restSubscription.DeleteE2InstanceId(instanceId) } c.registry.DeleteRESTSubscription(&restSubId) + c.RemoveRESTSubscriptionFromDb(restSubId) }() c.UpdateCounter(cRestSubDelRespToXapp) @@ -569,6 +583,7 @@ func (c *Control) TestRestHandler(w http.ResponseWriter, r *http.Request) { if s == "emptydb" { xapp.Logger.Info("RemoveAllSubscriptionsFromSdl() called") c.RemoveAllSubscriptionsFromSdl() + c.RemoveAllRESTSubscriptionsFromSdl() return } @@ -1138,6 +1153,41 @@ func (c *Control) RemoveSubscriptionFromDb(subs *Subscription) { } } +//------------------------------------------------------------------- +// +//------------------------------------------------------------------- +func (c *Control) WriteRESTSubscriptionToDb(restSubId string, restSubs *RESTSubscription) { + xapp.Logger.Debug("WriteRESTSubscriptionToDb() restSubId = %s", restSubId) + err := c.WriteRESTSubscriptionToSdl(restSubId, restSubs) + if err != nil { + xapp.Logger.Error("%v", err) + } +} + +//------------------------------------------------------------------- +// +//------------------------------------------------------------------- +func (c *Control) UpdateRESTSubscriptionInDB(restSubId string, restSubs *RESTSubscription, removeRestSubscriptionFromDb bool) { + + if removeRestSubscriptionFromDb == true { + // Subscription was written in db already when subscription request was sent to BTS, except for merged request + c.RemoveRESTSubscriptionFromDb(restSubId) + } else { + c.WriteRESTSubscriptionToDb(restSubId, restSubs) + } +} + +//------------------------------------------------------------------- +// +//------------------------------------------------------------------- +func (c *Control) RemoveRESTSubscriptionFromDb(restSubId string) { + xapp.Logger.Debug("RemoveRESTSubscriptionFromDb() restSubId = %s", restSubId) + err := c.RemoveRESTSubscriptionFromSdl(restSubId) + if err != nil { + xapp.Logger.Error("%v", err) + } +} + func (c *Control) SendSubscriptionDeleteReq(subs *Subscription) { const ricRequestorId = 123 diff --git a/pkg/control/registry.go b/pkg/control/registry.go index 5259273..671cf51 100644 --- a/pkg/control/registry.go +++ b/pkg/control/registry.go @@ -40,7 +40,7 @@ type RESTSubscription struct { xAppIdToE2Id map[int64]int64 SubReqOngoing bool SubDelReqOngoing bool - Md5sumOngoing string + Md5sum string } func (r *RESTSubscription) AddE2InstanceId(instanceId uint32) { @@ -65,7 +65,7 @@ func (r *RESTSubscription) DeleteXappIdToE2Id(xAppEventInstanceID int64) { func (r *RESTSubscription) SetProcessed() { r.SubReqOngoing = false - r.Md5sumOngoing = "" + r.Md5sum = "" } type Registry struct { diff --git a/pkg/control/sdl.go b/pkg/control/sdl_e2SubsDb.go similarity index 88% rename from pkg/control/sdl.go rename to pkg/control/sdl_e2SubsDb.go index ac8b8fb..c2526bc 100644 --- a/pkg/control/sdl.go +++ b/pkg/control/sdl_e2SubsDb.go @@ -22,10 +22,11 @@ package control import ( "encoding/json" "fmt" + "strconv" + "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap" sdl "gerrit.o-ran-sc.org/r/ric-plt/sdlgo" "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp" - "strconv" ) type SubscriptionInfo struct { @@ -39,7 +40,7 @@ type SubscriptionInfo struct { } func CreateSdl() Sdlnterface { - return sdl.NewSdlInstance("submgr", sdl.NewDatabase()) + return sdl.NewSdlInstance("submgr_e2SubsDb", sdl.NewDatabase()) } func (c *Control) WriteSubscriptionToSdl(subId uint32, subs *Subscription) error { @@ -63,11 +64,11 @@ func (c *Control) WriteSubscriptionToSdl(subId uint32, subs *Subscription) error return fmt.Errorf("SDL: WriteSubscriptionToSdl() json.Marshal error: %s", err.Error()) } - if err = c.db.Set(strconv.FormatUint(uint64(subId), 10), jsonData); err != nil { + if err = c.e2SubsDb.Set(strconv.FormatUint(uint64(subId), 10), jsonData); err != nil { c.UpdateCounter(cSDLWriteFailure) return fmt.Errorf("SDL: WriteSubscriptionToSdl(): %s", err.Error()) } else { - xapp.Logger.Debug("SDL: Subscription written in db. subId = %v", subId) + xapp.Logger.Debug("SDL: Subscription written in e2SubsDb. subId = %v", subId) } return nil } @@ -76,12 +77,12 @@ func (c *Control) ReadSubscriptionFromSdl(subId uint32) (*Subscription, error) { // This function is now just for testing purpose key := strconv.FormatUint(uint64(subId), 10) - retMap, err := c.db.Get([]string{key}) + retMap, err := c.e2SubsDb.Get([]string{key}) if err != nil { c.UpdateCounter(cSDLReadFailure) return nil, fmt.Errorf("SDL: ReadSubscriptionFromSdl(): %s", err.Error()) } else { - xapp.Logger.Debug("SDL: Subscription read from db. subId = %v", subId) + xapp.Logger.Debug("SDL: Subscription read from e2SubsDb. subId = %v", subId) } subs := &Subscription{} @@ -134,10 +135,10 @@ func (c *Control) CreateSubscription(subscriptionInfo *SubscriptionInfo, jsonSub func (c *Control) RemoveSubscriptionFromSdl(subId uint32) error { key := strconv.FormatUint(uint64(subId), 10) - if err := c.db.Remove([]string{key}); err != nil { + if err := c.e2SubsDb.Remove([]string{key}); err != nil { return fmt.Errorf("SDL: RemoveSubscriptionfromSdl(): %s\n", err.Error()) } else { - xapp.Logger.Debug("SDL: Subscription removed from db. subId = %v", subId) + xapp.Logger.Debug("SDL: Subscription removed from e2SubsDb. subId = %v", subId) } return nil } @@ -153,10 +154,10 @@ func (c *Control) ReadAllSubscriptionsFromSdl() ([]uint32, map[uint32]*Subscript retMap := make(map[uint32]*Subscription) // Get all keys - keys, err := c.db.GetAll() + keys, err := c.e2SubsDb.GetAll() if err != nil { c.UpdateCounter(cSDLReadFailure) - return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl(), GetAll(). Error while reading keys from DBAAS %s\n", err.Error()) + return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl(), GetAll(). Error while reading E2 subscriptions keys from DBAAS %s\n", err.Error()) } if len(keys) == 0 { @@ -164,10 +165,10 @@ func (c *Control) ReadAllSubscriptionsFromSdl() ([]uint32, map[uint32]*Subscript } // Get all subscriptionInfos - iSubscriptionMap, err := c.db.Get(keys) + iSubscriptionMap, err := c.e2SubsDb.Get(keys) if err != nil { c.UpdateCounter(cSDLReadFailure) - return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl(), Get(): Error while reading subscriptions from DBAAS %s\n", err.Error()) + return nil, nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl(), Get(): Error while reading E2 subscriptions from DBAAS %s\n", err.Error()) } for _, iSubscriptionInfo := range iSubscriptionMap { @@ -209,11 +210,11 @@ func removeNumber(s []uint32, removedNum uint32) ([]uint32, error) { } func (c *Control) RemoveAllSubscriptionsFromSdl() error { - if err := c.db.RemoveAll(); err != nil { + if err := c.e2SubsDb.RemoveAll(); err != nil { c.UpdateCounter(cSDLRemoveFailure) return fmt.Errorf("SDL: RemoveAllSubscriptionsFromSdl(): %s\n", err.Error()) } else { - xapp.Logger.Debug("SDL: All subscriptions removed from db") + xapp.Logger.Debug("SDL: All subscriptions removed from e2SubsDb") } return nil } diff --git a/pkg/control/sdl_test.go b/pkg/control/sdl_e2SubsDb_test.go similarity index 98% rename from pkg/control/sdl_test.go rename to pkg/control/sdl_e2SubsDb_test.go index 2fac9b2..2deb4b5 100644 --- a/pkg/control/sdl_test.go +++ b/pkg/control/sdl_e2SubsDb_test.go @@ -46,7 +46,7 @@ const ( ) type Mock struct { - subsDB map[string]string // Store information as a string like real db does. + e2SubsDb map[string]string // Store information as a string like real db does. register map[uint32]*Subscription subIds []uint32 lastAllocatedSubId uint32 @@ -63,7 +63,7 @@ func CreateMock() *Mock { } func (m *Mock) ResetTestSettings() { - m.subsDB = make(map[string]string) + m.e2SubsDb = make(map[string]string) m.register = make(map[uint32]*Subscription) var i uint32 for i = 1; i < 65535; i++ { @@ -490,7 +490,7 @@ func (m *Mock) Set(pairs ...interface{}) error { } if key != "" { - m.subsDB[key] = val + m.e2SubsDb[key] = val subId := m.subIds[0] subscriptionInfo := &SubscriptionInfo{} err := json.Unmarshal([]byte(val), subscriptionInfo) @@ -519,7 +519,7 @@ func (m *Mock) Get(keys []string) (map[string]interface{}, error) { for _, key := range keys { if key != "" { - retMap[key] = m.subsDB[key] + retMap[key] = m.e2SubsDb[key] } else { return nil, fmt.Errorf("Get() error: key == ''\n") } @@ -534,7 +534,7 @@ func (m *Mock) GetAll() ([]string, error) { } keys := []string{} - for key, _ := range m.subsDB { + for key, _ := range m.e2SubsDb { keys = append(keys, key) } return keys, nil @@ -554,7 +554,7 @@ func (m *Mock) Remove(keys []string) error { } subId := uint32(subId64) - delete(m.subsDB, keys[0]) + delete(m.e2SubsDb, keys[0]) delete(m.register, subId) m.subIds = append(m.subIds, subId) return nil @@ -562,14 +562,14 @@ func (m *Mock) Remove(keys []string) error { func (m *Mock) RemoveAll() error { - for key := range m.subsDB { + for key := range m.e2SubsDb { subId64, err := strconv.ParseUint(key, 10, 64) if err != nil { return fmt.Errorf("RemoveAll() ParseUint() error: %s\n", err.Error()) } subId := uint32(subId64) - delete(m.subsDB, key) + delete(m.e2SubsDb, key) delete(m.register, subId) m.subIds = append(m.subIds, subId) } diff --git a/pkg/control/sdl_restSubsDb.go b/pkg/control/sdl_restSubsDb.go new file mode 100644 index 0000000..782108f --- /dev/null +++ b/pkg/control/sdl_restSubsDb.go @@ -0,0 +1,174 @@ +/* + ================================================================================== + Copyright (c) 2019 AT&T Intellectual Property. + Copyright (c) 2019 Nokia + + 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. + ================================================================================== +*/ + +package control + +import ( + "encoding/json" + "fmt" + + sdl "gerrit.o-ran-sc.org/r/ric-plt/sdlgo" + "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp" +) + +type RESTSubscriptionInfo struct { + xAppRmrEndPoint string + Meid string + InstanceIds []uint32 + xAppIdToE2Id map[int64]int64 + SubReqOngoing bool + SubDelReqOngoing bool + Md5sum string +} + +func CreateRESTSdl() Sdlnterface { + return sdl.NewSdlInstance("submgr_restSubsDb", sdl.NewDatabase()) +} + +func (c *Control) WriteRESTSubscriptionToSdl(restSubId string, restSubs *RESTSubscription) error { + + var restSubscriptionInfo RESTSubscriptionInfo + restSubscriptionInfo.xAppRmrEndPoint = restSubs.xAppRmrEndPoint + restSubscriptionInfo.Meid = restSubs.Meid + restSubscriptionInfo.InstanceIds = restSubs.InstanceIds + restSubscriptionInfo.xAppIdToE2Id = restSubs.xAppIdToE2Id + restSubscriptionInfo.SubReqOngoing = restSubs.SubReqOngoing + restSubscriptionInfo.SubDelReqOngoing = restSubs.SubDelReqOngoing + restSubscriptionInfo.Md5sum = restSubs.Md5sum + + jsonData, err := json.Marshal(restSubscriptionInfo) + if err != nil { + return fmt.Errorf("SDL: WriteSubscriptionToSdl() json.Marshal error: %s", err.Error()) + } + + if err = c.restSubsDb.Set(restSubId, jsonData); err != nil { + c.UpdateCounter(cSDLWriteFailure) + return fmt.Errorf("SDL: WriteSubscriptionToSdl(): %s", err.Error()) + } else { + xapp.Logger.Debug("SDL: Subscription written in restSubsDb. restSubId = %v", restSubId) + } + return nil +} + +func (c *Control) ReadRESTSubscriptionFromSdl(restSubId string) (*RESTSubscription, error) { + + // This function is now just for testing purpose + key := restSubId + retMap, err := c.restSubsDb.Get([]string{key}) + if err != nil { + c.UpdateCounter(cSDLReadFailure) + return nil, fmt.Errorf("SDL: ReadSubscriptionFromSdl(): %s", err.Error()) + } else { + xapp.Logger.Debug("SDL: Subscription read from restSubsDb. restSubId = %v", restSubId) + } + + restSubs := &RESTSubscription{} + for _, iRESTSubscriptionInfo := range retMap { + + if iRESTSubscriptionInfo == nil { + return nil, fmt.Errorf("SDL: ReadSubscriptionFromSdl() REST subscription not found. restSubId = %v\n", restSubId) + } + + restSubscriptionInfo := &RESTSubscriptionInfo{} + jsonSubscriptionInfo := iRESTSubscriptionInfo.(string) + + if err := json.Unmarshal([]byte(jsonSubscriptionInfo), restSubscriptionInfo); err != nil { + return nil, fmt.Errorf("SDL: ReadSubscriptionFromSdl() json.unmarshal error: %s\n", err.Error()) + } + + restSubs = c.CreateRESTSubscription(restSubscriptionInfo, &jsonSubscriptionInfo) + } + return restSubs, nil +} + +func (c *Control) CreateRESTSubscription(restSubscriptionInfo *RESTSubscriptionInfo, jsonSubscriptionInfo *string) *RESTSubscription { + + restSubs := &RESTSubscription{} + restSubs.xAppRmrEndPoint = restSubscriptionInfo.xAppRmrEndPoint + restSubs.Meid = restSubscriptionInfo.Meid + restSubs.InstanceIds = restSubscriptionInfo.InstanceIds + restSubs.xAppIdToE2Id = restSubscriptionInfo.xAppIdToE2Id + restSubs.SubReqOngoing = restSubscriptionInfo.SubReqOngoing + restSubs.SubDelReqOngoing = restSubscriptionInfo.SubDelReqOngoing + restSubs.Md5sum = restSubscriptionInfo.Md5sum + + return restSubs +} + +func (c *Control) RemoveRESTSubscriptionFromSdl(restSubId string) error { + + key := restSubId + if err := c.restSubsDb.Remove([]string{key}); err != nil { + return fmt.Errorf("SDL: RemoveSubscriptionfromSdl(): %s\n", err.Error()) + } else { + xapp.Logger.Debug("SDL: Subscription removed from restSubsDb. restSubId = %v", restSubId) + } + return nil +} + +func (c *Control) ReadAllRESTSubscriptionsFromSdl() (map[string]*RESTSubscription, error) { + + retMap := make(map[string]*RESTSubscription) + // Get all keys + keys, err := c.restSubsDb.GetAll() + if err != nil { + c.UpdateCounter(cSDLReadFailure) + return nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl(), GetAll(). Error while reading REST subscriptions keys from DBAAS %s\n", err.Error()) + } + + if len(keys) == 0 { + return retMap, nil + } + + // Get all subscriptionInfos + iRESTSubscriptionMap, err := c.restSubsDb.Get(keys) + if err != nil { + c.UpdateCounter(cSDLReadFailure) + return nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl(), Get(): Error while reading REST subscriptions from DBAAS %s\n", err.Error()) + } + + for iRESTSubId, iRESTSubscriptionInfo := range iRESTSubscriptionMap { + + if iRESTSubscriptionInfo == nil { + return nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl() iRESTSubscriptionInfo = nil\n") + } + + restSubscriptionInfo := &RESTSubscriptionInfo{} + jsonSubscriptionInfo := iRESTSubscriptionInfo.(string) + + if err := json.Unmarshal([]byte(jsonSubscriptionInfo), restSubscriptionInfo); err != nil { + return nil, fmt.Errorf("SDL: ReadAllSubscriptionsFromSdl() json.unmarshal error: %s\n", err.Error()) + } + + restSubs := c.CreateRESTSubscription(restSubscriptionInfo, &jsonSubscriptionInfo) + retMap[iRESTSubId] = restSubs + } + return retMap, nil +} + +func (c *Control) RemoveAllRESTSubscriptionsFromSdl() error { + + if err := c.restSubsDb.RemoveAll(); err != nil { + c.UpdateCounter(cSDLRemoveFailure) + return fmt.Errorf("SDL: RemoveAllSubscriptionsFromSdl(): %s\n", err.Error()) + } else { + xapp.Logger.Debug("SDL: All subscriptions removed from e2SubsDb") + } + return nil +} diff --git a/pkg/control/sdl_restSubsDb_test.go b/pkg/control/sdl_restSubsDb_test.go new file mode 100644 index 0000000..ac3c8e3 --- /dev/null +++ b/pkg/control/sdl_restSubsDb_test.go @@ -0,0 +1,486 @@ +/* + ================================================================================== + Copyright (c) 2019 AT&T Intellectual Property. + Copyright (c) 2019 Nokia + + 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. + ================================================================================== +*/ + +package control + +import ( + "encoding/json" + "fmt" + "reflect" + "strings" + "sync" + "testing" + + "github.com/segmentio/ksuid" + "github.com/stretchr/testify/assert" +) + +var sdlRestShouldReturnError bool = false + +const sdlRestTestErrorString string = "Test sdl REST returned error on purpose" + +type RestSubsDbMock struct { + restSubsDb map[string]string // Store information as a string like real db does. + restSubscriptions map[string]*RESTSubscription + lastAllocatedRestSubId string + restSubIdsInDb []string + marshalLock sync.Mutex +} + +var restSubsDbMock *RestSubsDbMock + +func CreateRestSubsDbMock() *RestSubsDbMock { + fmt.Println("Test CreateRestSubsDbMock()") + restSubsDbMock = new(RestSubsDbMock) + restSubsDbMock.ResetTestSettings() + restSubsDbMock.lastAllocatedRestSubId = "" + return restSubsDbMock +} + +func (m *RestSubsDbMock) ResetTestSettings() { + m.restSubsDb = make(map[string]string) + m.restSubscriptions = make(map[string]*RESTSubscription) +} + +func (m *RestSubsDbMock) AllocNextRestSubId() string { + m.lastAllocatedRestSubId = ksuid.New().String() + return m.lastAllocatedRestSubId +} + +func (m *RestSubsDbMock) GetLastAllocatedRestSubId() string { + return m.lastAllocatedRestSubId +} + +func (m *RestSubsDbMock) AddRestSubIdsInDb(restSubId string) { + m.restSubIdsInDb = append(m.restSubIdsInDb, restSubId) +} + +func (m *RestSubsDbMock) DeleteRestSubIdsFromDb(restSubId string) { + newrestSubIdsInDb := []string{} + for _, i := range m.restSubIdsInDb { + if i != restSubId { + newrestSubIdsInDb = append(newrestSubIdsInDb, i) + } + } + m.restSubIdsInDb = newrestSubIdsInDb +} + +func (m *RestSubsDbMock) EmptyRestSubIdsFromDb() { + m.restSubIdsInDb = nil +} + +func CreateRESTSubscription(t *testing.T) *RESTSubscription { + t.Log("TEST: Creating REST subscription") + + restSubscription := &RESTSubscription{} + restSubscription.xAppRmrEndPoint = "localhost:13560" + restSubscription.Meid = "RAN_NAME_1" + restSubscription.SubReqOngoing = true + restSubscription.SubDelReqOngoing = false + restSubscription.xAppIdToE2Id = make(map[int64]int64) + restSubscription.Md5sum = "856e9546f6f7b65a13a86996f2d1686a" + return restSubscription +} + +func PrintRESTSubscriptionData(t *testing.T, restSubs *RESTSubscription) { + t.Log("TEST: RESTSubscription data") + t.Logf("TEST: restSubs.xAppRmrEndPoint = %v", restSubs.xAppRmrEndPoint) + t.Logf("TEST: restSubs.Meid = %v", restSubs.Meid) + t.Logf("TEST: restSubs.InstanceIds = %v", restSubs.InstanceIds) + t.Logf("TEST: restSubs.xAppIdToE2Id = %v", restSubs.xAppIdToE2Id) + t.Logf("TEST: restSubs.SubReqOngoing = %v", restSubs.SubReqOngoing) + t.Logf("TEST: restSubs.SubDelReqOngoing = %v", restSubs.SubDelReqOngoing) +} + +func TestWriteRESTSubscriptionToSdl(t *testing.T) { + + // Write one subscription + restSubId := restSubsDbMock.AllocNextRestSubId() + restSubs := CreateRESTSubscription(t) + PrintRESTSubscriptionData(t, restSubs) + t.Logf("TEST: Writing subId = %v\n", restSubId) + err := mainCtrl.c.WriteRESTSubscriptionToSdl(restSubId, restSubs) + if err != nil { + t.Errorf("TEST: %s", err.Error()) + } + restSubsDbMock.AddRestSubIdsInDb(restSubId) +} + +func TestReadRESTSubscriptionFromSdl(t *testing.T) { + + restSubId := restSubsDbMock.GetLastAllocatedRestSubId() + t.Logf("Reading restSubId = %v\n", restSubId) + restSubs, err := mainCtrl.c.ReadRESTSubscriptionFromSdl(restSubId) + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + PrintRESTSubscriptionData(t, restSubs) + assert.Equal(t, restSubsDbMock.restSubscriptions[restSubId], restSubs) +} + +func TestRemoveRESTSubscriptionFromSdl(t *testing.T) { + + restSubId := restSubsDbMock.GetLastAllocatedRestSubId() + err := mainCtrl.c.RemoveRESTSubscriptionFromSdl(restSubId) + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + delete(restSubsDbMock.restSubscriptions, restSubId) + t.Logf("TEST: REST subscription removed from db. subId = %v", restSubId) + restSubsDbMock.DeleteRestSubIdsFromDb(restSubId) +} + +func TestReadNotExistingRESTSubscriptionFromSdl(t *testing.T) { + + restSubId := "" + restSubs, err := mainCtrl.c.ReadRESTSubscriptionFromSdl(restSubId) + if err != nil { + t.Logf("TEST: REST subscription not found from db. restSubId = %v", restSubId) + return + } + t.Errorf("TEST: REST subscription read from db. %v", restSubs) + PrintRESTSubscriptionData(t, restSubs) +} + +func TestReadNotExistingRESTSubscriptionFromSdl2(t *testing.T) { + + restSubId := "NotExistingSubsId" + restSubs, err := mainCtrl.c.ReadRESTSubscriptionFromSdl(restSubId) + if err != nil { + t.Logf("TEST: REST subscription not found from db. restSubId = %v", restSubId) + return + } + t.Errorf("TEST: REST subscription read from db. %v", restSubs) + PrintRESTSubscriptionData(t, restSubs) +} + +func TestRemoveNotExistingRESTSubscriptionFromSdl(t *testing.T) { + + restSubId := "" + err := mainCtrl.c.RemoveRESTSubscriptionFromSdl(restSubId) + if err != nil { + t.Logf("TEST: %s", err.Error()) + return + } + t.Logf("TEST: REST subscription removed from db. subId = %v", restSubId) +} + +func TestWriteRESTSubscriptionsToSdl(t *testing.T) { + + // Write 1st subscription + restSubId := restSubsDbMock.AllocNextRestSubId() + t.Logf("TEST: Writing restSubId = %v\n", restSubId) + restSubs := CreateRESTSubscription(t) + PrintRESTSubscriptionData(t, restSubs) + err := mainCtrl.c.WriteRESTSubscriptionToSdl(restSubId, restSubs) + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + restSubsDbMock.AddRestSubIdsInDb(restSubId) + t.Logf("TEST: REST subscription written in db = %v", restSubs) + + // Write 2nd subscription + restSubId = restSubsDbMock.AllocNextRestSubId() + t.Logf("TEST:Writing restSubId = %v\n", restSubId) + restSubs = CreateRESTSubscription(t) + PrintRESTSubscriptionData(t, restSubs) + err = mainCtrl.c.WriteRESTSubscriptionToSdl(restSubId, restSubs) + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + restSubsDbMock.AddRestSubIdsInDb(restSubId) + t.Logf("TEST: REST subscription written in db = %v", restSubs) + + // Write 3rd subscription + restSubId = restSubsDbMock.AllocNextRestSubId() + t.Logf("TEST: Writing restSubId = %v\n", restSubId) + restSubs = CreateRESTSubscription(t) + PrintRESTSubscriptionData(t, restSubs) + err = mainCtrl.c.WriteRESTSubscriptionToSdl(restSubId, restSubs) + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + restSubsDbMock.AddRestSubIdsInDb(restSubId) + t.Logf("TEST: REST subscription written in db = %v", restSubs) +} + +func TestReadRESTSubscriptionsFromSdl(t *testing.T) { + + for _, restSubId := range restSubsDbMock.restSubIdsInDb { + restSubs, err := mainCtrl.c.ReadRESTSubscriptionFromSdl(restSubId) + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + PrintRESTSubscriptionData(t, restSubs) + } +} + +func TestReadAllRESTSubscriptionsFromSdl(t *testing.T) { + + register, err := mainCtrl.c.ReadAllRESTSubscriptionsFromSdl() + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + + for _, restSubs := range register { + PrintRESTSubscriptionData(t, restSubs) + } + + assert.Equal(t, len(register), 3) +} + +func TestRemoveAllRESTSubscriptionsFromSdl(t *testing.T) { + + err := mainCtrl.c.RemoveAllRESTSubscriptionsFromSdl() + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + t.Log("TEST: All subscription removed from db") + restSubsDbMock.EmptyRestSubIdsFromDb() +} + +func TestReadAllRESTSubscriptionsFromSdl2(t *testing.T) { + + register, err := mainCtrl.c.ReadAllRESTSubscriptionsFromSdl() + if err != nil { + t.Errorf("TEST: %s", err.Error()) + return + } + for _, restSubs := range restSubsDbMock.restSubscriptions { + PrintRESTSubscriptionData(t, restSubs) + } + assert.Equal(t, len(register), 0) +} + +func TestWriteRESTSubscriptionToSdlFail(t *testing.T) { + + // Try to write one subscription. + // Test db should return test error string + MakeNextSdlRestCallFail() + restsubId := restSubsDbMock.AllocNextRestSubId() + restSubs := CreateRESTSubscription(t) + PrintRESTSubscriptionData(t, restSubs) + t.Logf("TEST: Writing subId = %v\n", restsubId) + err := mainCtrl.c.WriteRESTSubscriptionToSdl(restsubId, restSubs) + if err != nil { + if !strings.Contains(fmt.Sprintf("%s", err), sdlRestTestErrorString) { + t.Errorf("TEST: %s", err.Error()) + } + } else { + t.Errorf("TEST: This test case should return error") + } +} + +func TestReadRESTSubscriptionFromSdlFail(t *testing.T) { + + // Try to read one subscription. + // Test db should return test error string + MakeNextSdlRestCallFail() + restSubId := restSubsDbMock.GetLastAllocatedRestSubId() + t.Logf("Reading restSubId = %v\n", restSubId) + restSubs, err := mainCtrl.c.ReadRESTSubscriptionFromSdl(restSubId) + if err != nil { + if !strings.Contains(fmt.Sprintf("%s", err), sdlRestTestErrorString) { + t.Errorf("TEST: %s", err.Error()) + } + return + } else { + t.Errorf("TEST: This test case should return error") + } + PrintRESTSubscriptionData(t, restSubs) +} + +func TestRemoveRESTSubscriptionFromSdlFail(t *testing.T) { + + // Try to remove one subscription. + // Test db should return test error string + MakeNextSdlRestCallFail() + restSubId := restSubsDbMock.GetLastAllocatedRestSubId() + err := mainCtrl.c.RemoveRESTSubscriptionFromSdl(restSubId) + if err != nil { + if !strings.Contains(fmt.Sprintf("%s", err), sdlRestTestErrorString) { + t.Errorf("TEST: %s", err.Error()) + } + return + } else { + t.Errorf("TEST: This test case should return error") + } + t.Logf("TEST: subscription removed from db. subId = %v", restSubId) +} + +func TestReadAllRESTSubscriptionsFromSdlFail(t *testing.T) { + + // Try to read all subscriptions. + // Test db should return test error string + MakeNextSdlRestCallFail() + register, err := mainCtrl.c.ReadAllRESTSubscriptionsFromSdl() + if err != nil { + if !strings.Contains(fmt.Sprintf("%s", err), sdlRestTestErrorString) { + t.Errorf("TEST: %s", err.Error()) + } + return + } else { + t.Errorf("TEST: This test case should return error") + } + + for _, restSubs := range register { + PrintRESTSubscriptionData(t, restSubs) + } +} + +func TestRemoveAllRESTSubscriptionsFromSdlFail(t *testing.T) { + + // Try to remove all subscriptions. + // Test db should return test error string + MakeNextSdlRestCallFail() + err := mainCtrl.c.RemoveAllRESTSubscriptionsFromSdl() + if err != nil { + if !strings.Contains(fmt.Sprintf("%s", err), sdlRestTestErrorString) { + t.Errorf("TEST: %s", err.Error()) + } + return + } else { + t.Errorf("TEST: This test case should return error") + } + t.Log("TEST: All subscription removed from db") +} + +func (m *RestSubsDbMock) Set(pairs ...interface{}) error { + var key string + var val string + + m.marshalLock.Lock() + defer m.marshalLock.Unlock() + + if sdlRestShouldReturnError == true { + return GetSdlRestError() + } + + for _, v := range pairs { + reflectType := reflect.TypeOf(v) + switch reflectType.Kind() { + case reflect.Slice: + val = fmt.Sprintf("%s", v.([]uint8)) + default: + switch v.(type) { + case string: + key = v.(string) + default: + return fmt.Errorf("Set() error: Unexpected type\n") + } + } + } + + if key != "" { + m.restSubsDb[key] = val + restSubId := key + restSubscriptionInfo := &RESTSubscriptionInfo{} + err := json.Unmarshal([]byte(val), restSubscriptionInfo) + if err != nil { + return fmt.Errorf("Set() json.unmarshal error: %s\n", err.Error()) + } + + restSubs := mainCtrl.c.CreateRESTSubscription(restSubscriptionInfo, &val) + m.restSubscriptions[restSubId] = restSubs + } else { + return fmt.Errorf("Set() error: key == ''\n") + } + return nil +} + +func (m *RestSubsDbMock) Get(keys []string) (map[string]interface{}, error) { + retMap := make(map[string]interface{}) + if len(keys) == 0 { + return nil, fmt.Errorf("Get() error: len(key) == 0\n") + } + + if sdlRestShouldReturnError == true { + return nil, GetSdlRestError() + } + + for _, key := range keys { + if key != "" { + retMap[key] = m.restSubsDb[key] + } else { + return nil, fmt.Errorf("Get() error: key == ''\n") + } + } + return retMap, nil +} + +func (m *RestSubsDbMock) GetAll() ([]string, error) { + + if sdlRestShouldReturnError == true { + return nil, GetSdlRestError() + } + + keys := []string{} + for key, _ := range m.restSubsDb { + keys = append(keys, key) + } + return keys, nil +} + +func (m *RestSubsDbMock) Remove(keys []string) error { + if len(keys) == 0 { + return fmt.Errorf("Remove() error: len(key) == 0\n") + } + + if sdlRestShouldReturnError == true { + return GetSdlRestError() + } + + restSubId := keys[0] + delete(m.restSubsDb, restSubId) + delete(m.restSubscriptions, restSubId) + return nil +} + +func (m *RestSubsDbMock) RemoveAll() error { + + for key := range m.restSubsDb { + + restSubId := key + delete(m.restSubsDb, restSubId) + delete(m.restSubscriptions, restSubId) + } + + if sdlRestShouldReturnError == true { + return GetSdlRestError() + } + + return nil +} + +func MakeNextSdlRestCallFail() { + sdlRestShouldReturnError = true +} + +func GetSdlRestError() error { + sdlRestShouldReturnError = false + return fmt.Errorf(sdlRestTestErrorString) +} diff --git a/pkg/control/ut_ctrl_submgr_test.go b/pkg/control/ut_ctrl_submgr_test.go index bd81127..ee7bc82 100644 --- a/pkg/control/ut_ctrl_submgr_test.go +++ b/pkg/control/ut_ctrl_submgr_test.go @@ -56,7 +56,8 @@ func createSubmgrControl(srcId teststub.RmrSrcId, rtgSvc teststub.RmrRtgSvc) *te mainCtrl.RmrControl.Init("SUBMGRCTL", srcId, rtgSvc) mainCtrl.c = NewControl() xapp.Logger.Debug("Replacing real db with test db") - mainCtrl.c.db = CreateMock() // This overrides real database for testing + mainCtrl.c.e2SubsDb = CreateMock() // This overrides real E2 Subscription database for testing + mainCtrl.c.restSubsDb = CreateRestSubsDbMock() // This overrides real REST Subscription database for testing xapp.SetReadyCB(mainCtrl.ReadyCB, nil) go xapp.RunWithParams(mainCtrl.c, false) mainCtrl.WaitCB() -- 2.16.6