[RICPLT-2492] - RSM - Read & Write from RSM DB the General Configuration. 00/1600/1
authorrh362j <ronen.hasid@intl.att.com>
Thu, 14 Nov 2019 14:52:53 +0000 (16:52 +0200)
committerrh362j <ronen.hasid@intl.att.com>
Thu, 14 Nov 2019 14:53:34 +0000 (16:53 +0200)
Change-Id: I82724545d4dc05cd3e8c5df6afc2f57b897063d0
Signed-off-by: rh362j <ronen.hasid@intl.att.com>
RSM/converters/x2apPdu_asn1_unpacker.go
RSM/e2pdus/resource_status_request.go
RSM/handlers/rmrmsghandlers/resource_status_failure_handler.go
RSM/mocks/rsm_writer_mock.go
RSM/rsmdb/rsm_reader.go
RSM/rsmdb/rsm_reader_test.go [new file with mode: 0644]
RSM/rsmdb/rsm_writer.go
RSM/rsmdb/rsm_writer_test.go [new file with mode: 0644]

index e95b7ee..d8f817c 100644 (file)
@@ -44,8 +44,6 @@ func (r X2apPduUnpacker) UnpackX2apPdu(packedBuf []byte) (*C.E2AP_PDU_t, error)
                return nil, errors.New("allocation failure (pdu)")
        }
 
-       r.logger.Infof("#x2apPdu_asn1_unpacker.UnpackX2apPdu - Packed pdu(%d):%x", len(packedBuf), packedBuf)
-
        errBuf := make([]C.char, r.maxMessageBufferSize)
        if !C.per_unpack_pdu(pdu, C.ulong(len(packedBuf)), (*C.uchar)(unsafe.Pointer(&packedBuf[0])), C.ulong(len(errBuf)), &errBuf[0]) {
                return nil, errors.New(fmt.Sprintf("unpacking error: %s", C.GoString(&errBuf[0])))
index 7af3983..fdbbefd 100644 (file)
@@ -60,15 +60,15 @@ func BuildPackedResourceStatusRequest(registrationRequest enums.Registration_Req
        packedBufSize := C.ulong(len(packedBuf))
        pduAsString := ""
 
-       pLMNIdentities := make([]*C.char, len(request.CellIdList))
-       eUTRANCellIdentifiers := make([]*C.char, len(request.CellIdList))
+       pLMNIdentities := make([]*C.uchar, len(request.CellIdList))
+       eUTRANCellIdentifiers := make([]*C.uchar, len(request.CellIdList))
 
        for i, cellID := range request.CellIdList {
-               var pLMNIdentity, eUTRANCellIdentifier string
+               var pLMNIdentity, eUTRANCellIdentifier []byte
                if _, err := fmt.Sscanf(cellID, "%x:%x", &pLMNIdentity, &eUTRANCellIdentifier); err != nil {
                        return nil, "", fmt.Errorf("BuildPackedResourceStatusRequest() - unexpected CellID value [%s]@%d (want: \"<PLMNIdentifier>:<eUTRANCellIdentifier>\"), err: %s", cellID, i, err)
                }
-               pLMNIdentities[i], eUTRANCellIdentifiers[i] = C.CString(pLMNIdentity), C.CString(eUTRANCellIdentifier)
+               pLMNIdentities[i], eUTRANCellIdentifiers[i] = (*C.uchar)(C.CBytes(pLMNIdentity)), (*C.uchar)(C.CBytes(eUTRANCellIdentifier))
        }
 
        defer func() {
index f7f5fb6..924b3f7 100644 (file)
@@ -44,7 +44,7 @@ func (h ResourceStatusFailureHandler) Handle(request *models.RmrRequest) {
                        h.logger.Errorf("#ResourceStatusFailureHandler.Handle - RAN name: %s - unpack failed. Error: %v", request.RanName, err)
                        return
                }
-               h.logger.Infof("#ResourceStatusFailureHandler.Handle - RAN name: %s - message: %s", request.RanName, pduAsString)
+               h.logger.Debugf("#ResourceStatusFailureHandler.Handle - RAN name: %s - message: %s", request.RanName, pduAsString)
        }
        response, err := h.converter.Convert(request.Payload)
        if err != nil {
index a2a62d8..bfabda7 100644 (file)
@@ -29,3 +29,8 @@ func (m *RsmWriterMock) SaveRsmRanInfo(rsmRanInfo *models.RsmRanInfo) error {
        args := m.Called(rsmRanInfo)
        return args.Error(0)
 }
+
+func (m *RsmWriterMock) SaveRsmGeneralConfiguration(cfg *models.RsmGeneralConfiguration) error {
+       args := m.Called(cfg)
+       return args.Error(0)
+}
index cb47ad2..852346b 100644 (file)
@@ -20,7 +20,6 @@ import (
        "encoding/json"
        "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
        "reflect"
-       "rsm/enums"
        "rsm/models"
 )
 
@@ -28,21 +27,18 @@ type rsmReaderInstance struct {
        sdl common.ISdlInstance
 }
 
-/*
-RNibReader interface allows retrieving data from redis BD by various keys
-*/
+// RsmReader interface allows retrieving data from redis BD by various keys
 type RsmReader interface {
        GetRsmGeneralConfiguration() (*models.RsmGeneralConfiguration, error)
        GetRsmRanInfo(ranName string) (*models.RsmRanInfo, error)
 }
 
-/*
-GetRNibReader returns reference to RNibReader
-*/
+// GetRsmReader returns reference to RsmReader
 func GetRsmReader(sdl common.ISdlInstance) RsmReader {
        return &rsmReaderInstance{sdl: sdl}
 }
 
+// GetRsmRanInfo returns the rsm data associated with ran 'ranName'
 func (r *rsmReaderInstance) GetRsmRanInfo(ranName string) (*models.RsmRanInfo, error) {
 
        key, err := common.ValidateAndBuildNodeBNameKey(ranName)
@@ -61,23 +57,14 @@ func (r *rsmReaderInstance) GetRsmRanInfo(ranName string) (*models.RsmRanInfo, e
        return rsmRanInfo, nil
 }
 
-// TODO: implement
+// GetRsmGeneralConfiguration returns resource status request related configuration
 func (r *rsmReaderInstance) GetRsmGeneralConfiguration() (*models.RsmGeneralConfiguration, error) {
-       return &models.RsmGeneralConfiguration{
-               EnableResourceStatus:         true,
-               PartialSuccessAllowed:        true,
-               PrbPeriodic:                  true,
-               TnlLoadIndPeriodic:           true,
-               HwLoadIndPeriodic:            true,
-               AbsStatusPeriodic:            true,
-               RsrpMeasurementPeriodic:      true,
-               CsiPeriodic:                  true,
-               PeriodicityMs:                enums.ReportingPeriodicity_one_thousand_ms,
-               PeriodicityRsrpMeasurementMs: enums.ReportingPeriodicityRSRPMR_four_hundred_80_ms,
-               PeriodicityCsiMs:             enums.ReportingPeriodicityCSIR_ms20,
-       }, nil
+       cfg := &models.RsmGeneralConfiguration{}
+       err := r.getByKeyAndUnmarshal(buildRsmGeneralConfigurationKey(), cfg)
+       return cfg, err
 }
 
+// getByKeyAndUnmarshal returns the value that is associated with key 'key' as a Go structure
 func (r *rsmReaderInstance) getByKeyAndUnmarshal(key string, entity interface{}) error {
        data, err := r.sdl.Get([]string{key})
        if err != nil {
@@ -92,3 +79,7 @@ func (r *rsmReaderInstance) getByKeyAndUnmarshal(key string, entity interface{})
        }
        return common.NewResourceNotFoundErrorf("#rsmReader.getByKeyAndUnmarshal - entity of type %s not found. Key: %s", reflect.TypeOf(entity).String(), key)
 }
+
+func buildRsmGeneralConfigurationKey() string {
+       return "CFG:GENERAL:v1.0.0"
+}
diff --git a/RSM/rsmdb/rsm_reader_test.go b/RSM/rsmdb/rsm_reader_test.go
new file mode 100644 (file)
index 0000000..e1703df
--- /dev/null
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ *
+ *   Copyright (c) 2019 AT&T Intellectual Property.
+ *
+ *   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 rsmdb
+
+import (
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+//     "gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
+       "github.com/stretchr/testify/assert"
+//     "os"
+       "rsm/enums"
+       "rsm/mocks"
+       "rsm/models"
+       "testing"
+)
+
+func TestGetRsmRanInfo(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       reader := GetRsmReader(sdl)
+       ranName := "test1"
+       key, _ := common.ValidateAndBuildNodeBNameKey(ranName)
+       infoAsGoType := models.RsmRanInfo{
+               RanName:           ranName,
+               Enb1MeasurementId: 1,
+               Enb2MeasurementId: 2,
+               Action:            enums.Start,
+               ActionStatus:      false,
+       }
+       infoAsDbType:= "{\"ranName\":\"test1\",\"enb1MeasurementId\":1,\"enb2MeasurementId\":2,\"action\":\"start\",\"actionStatus\":false}"
+       sdl.On("Get", []string{key}).Return(map[string]interface{}{key: infoAsDbType}, nil)
+       info, err := reader.GetRsmRanInfo(ranName)
+       if err != nil {
+               t.Errorf("want: success, got: error: %v\n", err)
+       }
+       assert.Equal(t, info, &infoAsGoType)
+}
+
+func TestGetRsmRanInfoValidationError(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       reader := GetRsmReader(sdl)
+       ranName := ""
+       key, _ := common.ValidateAndBuildNodeBNameKey(ranName)
+       sdl.On("Get", []string{key}).Return(map[string]interface{}{key: ""}, nil)
+       _, err := reader.GetRsmRanInfo(ranName)
+       assert.NotNil(t, err)
+       assert.Equal(t, err.Error(), "#utils.ValidateAndBuildNodeBNameKey - an empty inventory name received")
+}
+
+func TestGetRsmRanInfoDbError(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       reader := GetRsmReader(sdl)
+       ranName := "test1"
+       key, _ := common.ValidateAndBuildNodeBNameKey(ranName)
+       sdl.On("Get", []string{key}).Return((map[string]interface{})(nil), fmt.Errorf("db error"))
+       _, err := reader.GetRsmRanInfo(ranName)
+       assert.NotNil(t, err)
+       assert.Equal(t, err.Error(), "db error")
+}
+
+func TestGetGeneralConfiguration(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       reader := GetRsmReader(sdl)
+       var testCases = []struct {
+               cfgAsGoType models.RsmGeneralConfiguration
+               cfgAsDbType string
+       }{
+               {
+                       cfgAsGoType: models.RsmGeneralConfiguration{
+                               EnableResourceStatus:         true,
+                               PartialSuccessAllowed:        true,
+                               PrbPeriodic:                  true,
+                               TnlLoadIndPeriodic:           true,
+                               HwLoadIndPeriodic:            true,
+                               AbsStatusPeriodic:            true,
+                               RsrpMeasurementPeriodic:      true,
+                               CsiPeriodic:                  true,
+                               PeriodicityMs:                enums.ReportingPeriodicity_one_thousand_ms,
+                               PeriodicityRsrpMeasurementMs: enums.ReportingPeriodicityRSRPMR_four_hundred_80_ms,
+                               PeriodicityCsiMs:             enums.ReportingPeriodicityCSIR_ms20,
+                       },
+
+                       cfgAsDbType: "{\"enableResourceStatus\":true,\"partialSuccessAllowed\":true,\"prbPeriodic\":true,\"tnlLoadIndPeriodic\":true,\"wwLoadIndPeriodic\":true,\"absStatusPeriodic\":true,\"rsrpMeasurementPeriodic\":true,\"csiPeriodic\":true,\"periodicityMs\":1,\"periodicityRsrpMeasurementMs\":3,\"periodicityCsiMs\":3}",
+               },
+       }
+
+       for _, tc := range testCases {
+               t.Run(tc.cfgAsDbType, func(t *testing.T) {
+                       key := buildRsmGeneralConfigurationKey()
+                       sdl.On("Get", []string{key}).Return(map[string]interface{}{key: tc.cfgAsDbType}, nil)
+                       cfg, err := reader.GetRsmGeneralConfiguration()
+                       if err != nil {
+                               t.Errorf("want: success, got: error: %v\n", err)
+                       }
+                       assert.Equal(t, cfg, &tc.cfgAsGoType)
+               })
+       }
+}
+
+func TestGetGeneralConfigurationNotFound(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       reader := GetRsmReader(sdl)
+
+       key := buildRsmGeneralConfigurationKey()
+       sdl.On("Get", []string{key}).Return((map[string]interface{})(nil), nil)
+       _, err := reader.GetRsmGeneralConfiguration()
+       assert.NotNil(t, err)
+       assert.Equal(t, err.Error(), "#rsmReader.getByKeyAndUnmarshal - entity of type *models.RsmGeneralConfiguration not found. Key: CFG:GENERAL:v1.0.0")
+}
+
+func TestGetGeneralConfigurationDbError(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       reader := GetRsmReader(sdl)
+
+       key := buildRsmGeneralConfigurationKey()
+       sdl.On("Get", []string{key}).Return((map[string]interface{})(nil), fmt.Errorf("db error"))
+       _, err := reader.GetRsmGeneralConfiguration()
+       assert.NotNil(t, err)
+       assert.Equal(t, err.Error(), "db error")
+}
+
+func TestGetGeneralConfigurationUnmarshalError(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       reader := GetRsmReader(sdl)
+       cfgAsDbTYpe := "{\"enableResourceStatus\":true, partialSuccessAllowed\":true,\"prbPeriodic\":true,\"tnlLoadIndPeriodic\":true,\"wwLoadIndPeriodic\":true,\"absStatusPeriodic\":true,\"rsrpMeasurementPeriodic\":true,\"csiPeriodic\":true,\"periodicityMs\":1,\"periodicityRsrpMeasurementMs\":3,\"periodicityCsiMs\":3}"
+       key := buildRsmGeneralConfigurationKey()
+       sdl.On("Get", []string{key}).Return(map[string]interface{}{key: cfgAsDbTYpe}, nil)
+       _, err := reader.GetRsmGeneralConfiguration()
+       assert.NotNil(t, err)
+       assert.Equal(t, err.Error(), "invalid character 'p' looking for beginning of object key string")
+}
+
+/*
+Test against redis.
+Test execution depends on the existence of the environment variable DBAAS_SERVICE_HOST.
+*
+
+func TestGetGeneralConfigurationIntegration(t *testing.T) {
+       if len(os.Getenv("DBAAS_SERVICE_HOST")) == 0 {
+               return
+       }
+       db := sdlgo.NewDatabase()
+       sdl := sdlgo.NewSdlInstance("rsm", db)
+       reader := GetRsmReader(sdl)
+       cfgAsGoType := models.RsmGeneralConfiguration{
+               EnableResourceStatus:         true,
+               PartialSuccessAllowed:        true,
+               PrbPeriodic:                  true,
+               TnlLoadIndPeriodic:           true,
+               HwLoadIndPeriodic:            true,
+               AbsStatusPeriodic:            true,
+               RsrpMeasurementPeriodic:      true,
+               CsiPeriodic:                  true,
+               PeriodicityMs:                enums.ReportingPeriodicity_one_thousand_ms,
+               PeriodicityRsrpMeasurementMs: enums.ReportingPeriodicityRSRPMR_four_hundred_80_ms,
+               PeriodicityCsiMs:             enums.ReportingPeriodicityCSIR_ms20,
+       }
+       cfg, err := reader.GetRsmGeneralConfiguration()
+       if err != nil {
+               t.Errorf("want: success, got: error: %v\n", err)
+       }
+
+       assert.Equal(t, &cfgAsGoType, cfg)
+}
+*/
\ No newline at end of file
index fe7fa56..9a87689 100644 (file)
@@ -26,20 +26,18 @@ type rsmWriterInstance struct {
        sdl common.ISdlInstance
 }
 
-/*
-RNibReader interface allows retrieving data from redis BD by various keys
-*/
+// RsmWriter interface allows inserting/updating data to/in redis BD with various keys
 type RsmWriter interface {
        SaveRsmRanInfo(rsmRanInfo *models.RsmRanInfo) error
+       SaveRsmGeneralConfiguration(cfg *models.RsmGeneralConfiguration) error
 }
 
-/*
-GetRNibReader returns reference to RNibReader
-*/
+// GetRsmWriter returns reference to RsmWriter
 func GetRsmWriter(sdl common.ISdlInstance) RsmWriter {
        return &rsmWriterInstance{sdl: sdl}
 }
 
+// SaveRsmRanInfo saves the ran related rsm data with key RanName
 func (r *rsmWriterInstance) SaveRsmRanInfo(rsmRanInfo *models.RsmRanInfo) error {
 
        nodebNameKey, err := common.ValidateAndBuildNodeBNameKey(rsmRanInfo.RanName)
@@ -48,14 +46,27 @@ func (r *rsmWriterInstance) SaveRsmRanInfo(rsmRanInfo *models.RsmRanInfo) error
                return err
        }
 
-       data, err := json.Marshal(rsmRanInfo)
+       return r.SaveWithKeyAndMarshal(nodebNameKey, rsmRanInfo)
+}
+
+// SaveRsmGeneralConfiguration saves the resource status request related configuration
+func (r *rsmWriterInstance) SaveRsmGeneralConfiguration(cfg *models.RsmGeneralConfiguration) error {
+
+       return r.SaveWithKeyAndMarshal(buildRsmGeneralConfigurationKey(), cfg)
+}
+
+
+// SaveWithKeyAndMarshal marshals 
+func (r *rsmWriterInstance) SaveWithKeyAndMarshal(key string, entity interface{}) error {
+
+       data, err := json.Marshal(entity)
 
        if err != nil {
                return common.NewInternalError(err)
        }
 
        var pairs []interface{}
-       pairs = append(pairs, nodebNameKey, data)
+       pairs = append(pairs, key, data)
 
        err = r.sdl.Set(pairs)
 
diff --git a/RSM/rsmdb/rsm_writer_test.go b/RSM/rsmdb/rsm_writer_test.go
new file mode 100644 (file)
index 0000000..627c2f1
--- /dev/null
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ *
+ *   Copyright (c) 2019 AT&T Intellectual Property.
+ *
+ *   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 rsmdb
+
+import (
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+       "github.com/stretchr/testify/assert"
+       "rsm/enums"
+       "rsm/mocks"
+       "rsm/models"
+       "testing"
+)
+
+func TestSaveRsmRanInfo(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       writer := GetRsmWriter(sdl)
+       ranName := "test1"
+       key, _ := common.ValidateAndBuildNodeBNameKey(ranName)
+       infoAsGoType := models.RsmRanInfo{
+               RanName:           ranName,
+               Enb1MeasurementId: 1,
+               Enb2MeasurementId: 2,
+               Action:            enums.Start,
+               ActionStatus:      false,
+       }
+       infoAsDbType:= "{\"ranName\":\"test1\",\"enb1MeasurementId\":1,\"enb2MeasurementId\":2,\"action\":\"start\",\"actionStatus\":false}"
+       sdl.On("Set",[]interface{}{[]interface{}{key, []byte(infoAsDbType)}}).Return(nil)
+       err := writer.SaveRsmRanInfo(&infoAsGoType)
+       if err != nil {
+               t.Errorf("want: success, got: error: %v\n", err)
+       }
+       sdl.AssertNumberOfCalls(t, "Set",1)
+}
+
+
+func TestSaveRsmRanInfoValidationError(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       writer := GetRsmWriter(sdl)
+       ranName := ""
+       key, _ := common.ValidateAndBuildNodeBNameKey(ranName)
+       infoAsGoType := models.RsmRanInfo{
+               RanName:           ranName,
+               Enb1MeasurementId: 1,
+               Enb2MeasurementId: 2,
+               Action:            enums.Start,
+               ActionStatus:      false,
+       }
+       infoAsDbType:= "{\"ranName\":\"test1\",\"enb1MeasurementId\":1,\"enb2MeasurementId\":2,\"action\":\"start\",\"actionStatus\":false}"
+       sdl.On("Set",[]interface{}{[]interface{}{key, []byte(infoAsDbType)}}).Return(nil)
+       err := writer.SaveRsmRanInfo(&infoAsGoType)
+       assert.NotNil(t, err)
+       assert.Equal(t, err.Error(), "#utils.ValidateAndBuildNodeBNameKey - an empty inventory name received")
+}
+
+
+func TestSaveGeneralConfiguration(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       writer := GetRsmWriter(sdl)
+       var testCases = []struct {
+               cfgAsGoType models.RsmGeneralConfiguration
+               cfgAsDbType string
+       }{
+               {
+                       cfgAsGoType: models.RsmGeneralConfiguration{
+                               EnableResourceStatus:         true,
+                               PartialSuccessAllowed:        true,
+                               PrbPeriodic:                  true,
+                               TnlLoadIndPeriodic:           true,
+                               HwLoadIndPeriodic:            true,
+                               AbsStatusPeriodic:            true,
+                               RsrpMeasurementPeriodic:      true,
+                               CsiPeriodic:                  true,
+                               PeriodicityMs:                enums.ReportingPeriodicity_one_thousand_ms,
+                               PeriodicityRsrpMeasurementMs: enums.ReportingPeriodicityRSRPMR_four_hundred_80_ms,
+                               PeriodicityCsiMs:             enums.ReportingPeriodicityCSIR_ms20,
+                       },
+
+                       cfgAsDbType: "{\"enableResourceStatus\":true,\"partialSuccessAllowed\":true,\"prbPeriodic\":true,\"tnlLoadIndPeriodic\":true,\"wwLoadIndPeriodic\":true,\"absStatusPeriodic\":true,\"rsrpMeasurementPeriodic\":true,\"csiPeriodic\":true,\"periodicityMs\":1,\"periodicityRsrpMeasurementMs\":3,\"periodicityCsiMs\":3}",
+               },
+       }
+
+       for _, tc := range testCases {
+               t.Run(tc.cfgAsDbType, func(t *testing.T) {
+                       key:= buildRsmGeneralConfigurationKey()
+                       sdl.On("Set",[]interface{}{[]interface{}{key, []byte(tc.cfgAsDbType)}}).Return(nil)
+                       err := writer.SaveRsmGeneralConfiguration(&tc.cfgAsGoType)
+                       if err != nil {
+                               t.Errorf("want: success, got: error: %v\n", err)
+                       }
+
+                       sdl.AssertNumberOfCalls(t, "Set",1)
+               })
+       }
+}
+
+
+func TestSaveGeneralConfigurationDbError(t *testing.T) {
+       sdl := &mocks.MockSdlInstance{}
+       writer := GetRsmWriter(sdl)
+
+       cfgAsGoType:= models.RsmGeneralConfiguration{
+               EnableResourceStatus:         true,
+               PartialSuccessAllowed:        true,
+               PrbPeriodic:                  true,
+               TnlLoadIndPeriodic:           true,
+               HwLoadIndPeriodic:            true,
+               AbsStatusPeriodic:            true,
+               RsrpMeasurementPeriodic:      true,
+               CsiPeriodic:                  true,
+               PeriodicityMs:                enums.ReportingPeriodicity_one_thousand_ms,
+               PeriodicityRsrpMeasurementMs: enums.ReportingPeriodicityRSRPMR_four_hundred_80_ms,
+               PeriodicityCsiMs:             enums.ReportingPeriodicityCSIR_ms20,
+       }
+       cfgAsDbTYpe:= "{\"enableResourceStatus\":true,\"partialSuccessAllowed\":true,\"prbPeriodic\":true,\"tnlLoadIndPeriodic\":true,\"wwLoadIndPeriodic\":true,\"absStatusPeriodic\":true,\"rsrpMeasurementPeriodic\":true,\"csiPeriodic\":true,\"periodicityMs\":1,\"periodicityRsrpMeasurementMs\":3,\"periodicityCsiMs\":3}"
+       key:= buildRsmGeneralConfigurationKey()
+       sdl.On("Set",[]interface{}{[]interface{}{key, []byte(cfgAsDbTYpe)}}).Return(fmt.Errorf("db error"))
+       err := writer.SaveRsmGeneralConfiguration(&cfgAsGoType)
+       assert.NotNil(t, err)
+       assert.Equal(t, err.Error(), "db error")
+}