bool
build_pack_resource_status_request(
- uint8_t const* pLMN_Identity,
- uint8_t const* eUTRANCellIdentifier,
+ uint8_t const** pLMN_Identities,
+ uint8_t const** eUTRANCellIdentifiers,
+ size_t nECGIs,
Measurement_ID_t measurement_ID, Measurement_ID_t measurement_ID2,
Registration_Request_t registration_Request /*Registration_Request_start,Registration_Request_stop,Registration_Request_partial_stop, Registration_Request_add*/,
uint32_t reportCharacteristics,
bool
build_pack_resource_status_request_aux(
- uint8_t const* pLMN_Identity,
- uint8_t const* eUTRANCellIdentifier,
+ uint8_t const** pLMN_Identities,
+ uint8_t const** eUTRANCellIdentifiers,
+ size_t nECGIs,
Measurement_ID_t measurement_ID, Measurement_ID_t measurement_ID2,
Registration_Request_t registration_Request /*Registration_Request_start,Registration_Request_stop,Registration_Request_partial_stop, Registration_Request_add*/,
uint32_t reportCharacteristics,
--- /dev/null
+/*
+ *
+ * Copyright 2019 AT&T Intellectual Property
+ * Copyright 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.
+ *
+ */
+#ifndef INC_RESOURCE_STATUS_RESPONSE_WRAPPER_H
+#define INC_RESOURCE_STATUS_RESPONSE_WRAPPER_H
+
+#include <UnsuccessfulOutcome.h>
+#include <SuccessfulOutcome.h>
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INC_RESOURCE_STATUS_RESPONSE_WRAPPER_H */
bool
build_pack_resource_status_request(
- uint8_t const* pLMN_Identity,
- uint8_t const* eUTRANCellIdentifier,
+ uint8_t const** pLMN_Identities,
+ uint8_t const** eUTRANCellIdentifiers,
+ size_t nECGIs,
Measurement_ID_t measurement_ID, Measurement_ID_t measurement_ID2,
Registration_Request_t registration_Request /*Registration_Request_start,Registration_Request_stop,Registration_Request_partial_stop, Registration_Request_add*/,
uint32_t reportCharacteristics,
)
{
return build_pack_resource_status_request_aux(
- pLMN_Identity,
- eUTRANCellIdentifier,
+ pLMN_Identities,
+ eUTRANCellIdentifiers,
+ nECGIs,
measurement_ID, measurement_ID2,
registration_Request,
reportCharacteristics,
bool
build_pack_resource_status_request_aux(
- uint8_t const* pLMN_Identity,
- uint8_t const* eUTRANCellIdentifier,
+ uint8_t const** pLMN_Identities,
+ uint8_t const** eUTRANCellIdentifiers,
+ size_t nECGIs,
Measurement_ID_t measurement_ID, Measurement_ID_t measurement_ID2,
Registration_Request_t registration_Request /*Registration_Request_start,Registration_Request_stop,Registration_Request_partial_stop, Registration_Request_add*/,
uint32_t reportCharacteristics,
cellToReport_List_ie->criticality = Criticality_ignore;
cellToReport_List_ie->value.present = ResourceStatusRequest_IEs__value_PR_CellToReport_List;
- CellToReport_ItemIEs_t *item = calloc(1, sizeof(CellToReport_ItemIEs_t));
- assert(item != 0);
- ASN_SEQUENCE_ADD(&cellToReport_List_ie->value.choice.CellToReport_List, item);
+ for (size_t i = 0; i < nECGIs; i++){
+ CellToReport_ItemIEs_t *item = calloc(1, sizeof(CellToReport_ItemIEs_t));
+ assert(item != 0);
+ ASN_SEQUENCE_ADD(&cellToReport_List_ie->value.choice.CellToReport_List, item);
- item->id = ProtocolIE_ID_id_CellToReport_Item;
- item->criticality = Criticality_ignore;
- item->value.present = CellToReport_ItemIEs__value_PR_CellToReport_Item;
- assignPLMN_Identity(&item->value.choice.CellToReport_Item.cell_ID.pLMN_Identity, pLMN_Identity);
- assignEUTRANcellIdentifier(&item->value.choice.CellToReport_Item.cell_ID.eUTRANcellIdentifier,eUTRANCellIdentifier);
+ item->id = ProtocolIE_ID_id_CellToReport_Item;
+ item->criticality = Criticality_ignore;
+ item->value.present = CellToReport_ItemIEs__value_PR_CellToReport_Item;
+ assignPLMN_Identity(&item->value.choice.CellToReport_Item.cell_ID.pLMN_Identity, pLMN_Identities[i]);
+ assignEUTRANcellIdentifier(&item->value.choice.CellToReport_Item.cell_ID.eUTRANcellIdentifier,eUTRANCellIdentifiers[i]);
+ }
if (reportingPeriodicity >= 0){
ResourceStatusRequest_IEs_t *reportingPeriodicity_ie = calloc(1, sizeof(ResourceStatusRequest_IEs_t));
#include <resource_status_request_wrapper.h>
void test_build_pack_resource_status_request();
+ void test_build_pack_resource_status_request_stop();
void test_unpack(void);
int
main(int argc, char* argv[])
{
test_build_pack_resource_status_request();
+ test_build_pack_resource_status_request_stop();
exit(0);
}
size_t packed_buf_size = 4096;
unsigned char outBuf[packed_buf_size];
char errorBuf[error_buf_size];
- uint8_t pLMN_Identity[] = {0xa,0xb,0xc};
- uint8_t eUTRANCellIdentifier[] = {0xab, 0xcd, 0x70, 0};
+ const uint8_t pLMN_Identity[] = {0xa,0xb,0xc};
+ const uint8_t eUTRANCellIdentifier[] = {0xab, 0xcd, 0x70, 0};
+ const uint8_t *pLMN_Identities[] = {pLMN_Identity};
+ const uint8_t *eUTRANCellIdentifiers[] = {eUTRANCellIdentifier};
E2AP_PDU_t *pdu;
bool result = build_pack_resource_status_request(
- pLMN_Identity, eUTRANCellIdentifier,
+ pLMN_Identities, eUTRANCellIdentifiers, 1,
15 /*measurement_ID*/, 0 /*measurement_ID2*/,
Registration_Request_start /*Registration_Request_start,Registration_Request_stop,Registration_Request_partial_stop, Registration_Request_add*/,
0xf0,
}
+void test_build_pack_resource_status_request_stop(){
+ size_t error_buf_size = 8192;
+ size_t packed_buf_size = 4096;
+ unsigned char outBuf[packed_buf_size];
+ char errorBuf[error_buf_size];
+ const uint8_t pLMN_Identity[] = {0xa,0xb,0xc};
+ const uint8_t eUTRANCellIdentifier[] = {0xab, 0xcd, 0x70, 0};
+ const uint8_t *pLMN_Identities[] = {pLMN_Identity};
+ const uint8_t *eUTRANCellIdentifiers[] = {eUTRANCellIdentifier};
+ E2AP_PDU_t *pdu;
+
+ bool result = build_pack_resource_status_request(
+ pLMN_Identities, eUTRANCellIdentifiers, 1,
+ 15 /*measurement_ID*/, 2 /*measurement_ID2*/,
+ Registration_Request_stop /*Registration_Request_start,Registration_Request_stop,Registration_Request_partial_stop, Registration_Request_add*/,
+ 0,
+ ReportingPeriodicity_one_thousand_ms /*ReportingPeriodicity_one_thousand_ms, ReportingPeriodicity_two_thousand_ms, ReportingPeriodicity_five_thousand_ms,ReportingPeriodicity_ten_thousand_ms*/,
+ PartialSuccessIndicator_partial_success_allowed /*PartialSuccessIndicator_partial_success_allowed*/,
+ ReportingPeriodicityRSRPMR_one_hundred_20_ms /*ReportingPeriodicityRSRPMR_one_hundred_20_ms, ReportingPeriodicityRSRPMR_two_hundred_40_ms, ReportingPeriodicityRSRPMR_four_hundred_80_ms,ReportingPeriodicityRSRPMR_six_hundred_40_ms*/,
+ ReportingPeriodicityCSIR_ms5 /* ReportingPeriodicityCSIR_ms5, ReportingPeriodicityCSIR_ms10,ReportingPeriodicityCSIR_ms20,ReportingPeriodicityCSIR_ms40,ReportingPeriodicityCSIR_ms80*/,
+ &packed_buf_size, outBuf, error_buf_size, errorBuf);
+
+ if (!result) {
+ printf("#%s failed. Packing error %s\n", __func__,errorBuf);
+ return;
+ }
+ printf("packed size:%lu\nPayload:\n", packed_buf_size);
+ for (size_t i = 0; i < packed_buf_size; ++i)
+ printf("%02x",outBuf[i]);
+ printf("\n");
+
+ pdu = calloc(1, sizeof(E2AP_PDU_t));
+ if (!unpack_pdu_aux(pdu, packed_buf_size, outBuf,error_buf_size, errorBuf,ATS_ALIGNED_BASIC_PER)){
+ printf("#%s failed. Unpacking error %s\n", __func__, errorBuf);
+ }
+ errorBuf[0] = 0;
+ asn1_pdu_printer(pdu, sizeof(errorBuf), errorBuf);
+ printf("#%s: %s\n", __func__, errorBuf);
+
+ }
+
# platform project (RICP).
#
-FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:2-u16.04-nng as ubuntu
+FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu16-c-go:3-u16.04-nng as ubuntu
WORKDIR /opt/RSM
COPY . .
ENV PATH=$PATH:/usr/local/go/bin:/usr/lib/go-1.12/bin
# Install RMr library and dev files
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.10.0_amd64.deb/download.deb
-RUN dpkg -i rmr_1.10.0_amd64.deb
-RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr-dev_1.10.0_amd64.deb/download.deb
-RUN dpkg -i rmr-dev_1.10.0_amd64.deb
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.13.0_amd64.deb/download.deb
+RUN dpkg -i rmr_1.13.0_amd64.deb
+RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr-dev_1.13.0_amd64.deb/download.deb
+RUN dpkg -i rmr-dev_1.13.0_amd64.deb
RUN cd 3rdparty/asn1codec && make
import (
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
+ "gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
"os"
"rsm/configuration"
"rsm/controllers"
"rsm/converters"
+ "rsm/e2pdus"
"rsm/httpserver"
"rsm/logger"
- "rsm/managers"
"rsm/managers/rmrmanagers"
+ "rsm/providers/httpmsghandlerprovider"
"rsm/rmrcgo"
+ "rsm/rsmdb"
"rsm/services"
"rsm/services/rmrreceiver"
"rsm/services/rmrsender"
"strconv"
)
-const MaxRnibPoolInstances = 4
-
func main() {
config, err := configuration.ParseConfiguration()
if err != nil {
fmt.Printf("#app.main - failed to initialize logger, error: %s", err)
os.Exit(1)
}
- reader.Init("e2Manager", MaxRnibPoolInstances)
+ db := sdlgo.NewDatabase()
+ e2mSdl := sdlgo.NewSdlInstance("e2Manager", db)
+ rsmSdl := sdlgo.NewSdlInstance("rsm", db)
+
+ defer e2mSdl.Close()
+ defer rsmSdl.Close()
+
logger.Infof("#app.main - Configuration %s", config)
- defer reader.Close()
- rnibDataService := services.NewRnibDataService(logger, config, reader.GetRNibReader)
+ rnibDataService := services.NewRnibDataService(logger, config, reader.GetRNibReader(e2mSdl), rsmdb.GetRsmReader(rsmSdl), rsmdb.GetRsmWriter(rsmSdl))
var msgImpl *rmrcgo.Context
rmrMessenger := msgImpl.Init(config.Rmr.ReadyIntervalSec, "tcp:"+strconv.Itoa(config.Rmr.Port), config.Rmr.MaxMsgSize, 0, logger)
rmrSender := rmrsender.NewRmrSender(logger, rmrMessenger)
- resourceStatusInitiateManager := managers.NewResourceStatusInitiateManager(logger, rnibDataService, rmrSender)
- var rmrManager = rmrmanagers.NewRmrMessageManager(logger, config, rnibDataService, rmrSender, resourceStatusInitiateManager,converters.NewX2apPduUnpacker(logger))
+ resourceStatusService := services.NewResourceStatusService(logger, rmrSender)
+ unpacker := converters.NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ var rmrManager = rmrmanagers.NewRmrMessageManager(logger, config, rnibDataService, rmrSender, resourceStatusService, converters.NewResourceStatusResponseConverter(unpacker), converters.NewResourceStatusFailureConverter(unpacker))
rmrReceiver := rmrreceiver.NewRmrReceiver(logger, rmrMessenger, rmrManager)
defer rmrMessenger.Close()
go rmrReceiver.ListenAndHandle()
- //handlerProvider := httpmsghandlerprovider.NewRequestHandlerProvider(logger, rmrSender, config, rnibDataService)
+ handlerProvider := httpmsghandlerprovider.NewRequestHandlerProvider(logger, rnibDataService, resourceStatusService)
rootController := controllers.NewRootController(rnibDataService)
- //controller := controllers.NewController(logger, handlerProvider)
- _ = httpserver.Run(config.Http.Port, rootController)
-}
+ controller := controllers.NewController(logger, handlerProvider)
+ _ = httpserver.Run(config.Http.Port, rootController, controller)
+}
\ No newline at end of file
import (
"fmt"
"github.com/spf13/viper"
- "rsm/enums"
)
type Configuration struct {
MaxRnibConnectionAttempts int
RnibRetryIntervalMs int
}
- ResourceStatusParams struct {
- EnableResourceStatus bool
- PartialSuccessAllowed bool
- PrbPeriodic bool
- TnlLoadIndPeriodic bool
- HwLoadIndPeriodic bool
- AbsStatusPeriodic bool
- RsrpMeasurementPeriodic bool
- CsiPeriodic bool
- PeriodicityMs enums.ReportingPeriodicity
- PeriodicityRsrpMeasurementMs enums.ReportingPeriodicityRSRPMR
- PeriodicityCsiMs enums.ReportingPeriodicityCSIR
- }
}
func ParseConfiguration() (*Configuration, error) {
if err := config.fillRnibConfig(viper.Sub("rnib")); err != nil {
return nil, err
}
- if err := config.fillResourceStatusParamsConfig(viper.Sub("resourceStatusParams")); err != nil {
- return nil, err
- }
return &config, nil
}
return nil
}
-func (c *Configuration) fillResourceStatusParamsConfig(chConfig *viper.Viper) error {
- if chConfig == nil {
- return fmt.Errorf("#configuration.fillResourceStatusParamsConfig - failed to fill resourceStatusParams configuration: The entry 'resourceStatusParams' not found\n")
- }
- c.ResourceStatusParams.EnableResourceStatus = chConfig.GetBool("enableResourceStatus")
- c.ResourceStatusParams.PartialSuccessAllowed = chConfig.GetBool("partialSuccessAllowed")
- c.ResourceStatusParams.PrbPeriodic = chConfig.GetBool("prbPeriodic")
- c.ResourceStatusParams.TnlLoadIndPeriodic = chConfig.GetBool("tnlLoadIndPeriodic")
- c.ResourceStatusParams.HwLoadIndPeriodic = chConfig.GetBool("hwLoadIndPeriodic")
- c.ResourceStatusParams.AbsStatusPeriodic = chConfig.GetBool("absStatusPeriodic")
- c.ResourceStatusParams.RsrpMeasurementPeriodic = chConfig.GetBool("rsrpMeasurementPeriodic")
- c.ResourceStatusParams.CsiPeriodic = chConfig.GetBool("csiPeriodic")
- if err := setPeriodicityMs(c, chConfig.GetInt("periodicityMs")); err != nil {
- return err
- }
- if err := setPeriodicityRsrpMeasurementMs(c, chConfig.GetInt("periodicityRsrpMeasurementMs")); err != nil {
- return err
- }
- if err := setPeriodicityCsiMs(c, chConfig.GetInt("periodicityCsiMs")); err != nil {
- return err
- }
- return nil
-}
-
-func setPeriodicityMs(c *Configuration, periodicityMs int) error {
- v, ok := enums.ReportingPeriodicityValues[periodicityMs]
-
- if !ok {
- return fmt.Errorf("Invalid configuration value supplied for PeriodicityMs. Received: %d. Should be one of: %v\n", periodicityMs, enums.GetReportingPeriodicityValuesAsKeys())
- }
-
- c.ResourceStatusParams.PeriodicityMs = v
- return nil
-}
-
-func setPeriodicityRsrpMeasurementMs(c *Configuration, periodicityRsrpMeasurementMs int) error {
- v, ok := enums.ReportingPeriodicityRsrPmrValues[periodicityRsrpMeasurementMs]
-
- if !ok {
- return fmt.Errorf("Invalid configuration value supplied for PeriodicityRsrpMeasurementMs. Received: %d. Should be one of: %v\n", periodicityRsrpMeasurementMs, enums.GetReportingPeriodicityRsrPmrValuesAsKeys())
- }
-
- c.ResourceStatusParams.PeriodicityRsrpMeasurementMs = v
- return nil
-}
-
-func setPeriodicityCsiMs(c *Configuration, periodicityCsiMs int) error {
- v, ok := enums.ReportingPeriodicityCsirValues[periodicityCsiMs]
-
- if !ok {
- return fmt.Errorf("Invalid configuration value supplied for PeriodicityCsiMs. Received: %d. Should be one of: %v\n", periodicityCsiMs, enums.GetReportingPeriodicityCsirValuesAsKeys())
- }
-
- c.ResourceStatusParams.PeriodicityCsiMs = v
- return nil
-}
func (c *Configuration) String() string {
- return fmt.Sprintf("{logging.logLevel: %s, http.port: %d, rmr.port: %d, rmr.maxMsgSize: %d, rmr.readyIntervalSec: %d, rnib.maxRnibConnectionAttempts: %d, rnib.rnibRetryIntervalMs: %d, "+
- "resourceStatusParams.enableResourceStatus: %t, resourceStatusParams.partialSuccessAllowed: %t, resourceStatusParams.prbPeriodic: %t, "+
- "resourceStatusParams.tnlLoadIndPeriodic: %t, resourceStatusParams.hwLoadIndPeriodic: %t, resourceStatusParams.absStatusPeriodic: %t,"+
- "resourceStatusParams.rsrpMeasurementPeriodic: %t, resourceStatusParams.csiPeriodic: %t, resourceStatusParams.periodicityMs: %s, "+
- "resourceStatusParams.periodicityRsrpMeasurementMs: %s, resourceStatusParams.periodicityCsiMs: %s}",
+ return fmt.Sprintf("{logging.logLevel: %s, http.port: %d, rmr.port: %d, rmr.maxMsgSize: %d, rmr.readyIntervalSec: %d, rnib.maxRnibConnectionAttempts: %d, rnib.rnibRetryIntervalMs: %d, ",
c.Logging.LogLevel,
c.Http.Port,
c.Rmr.Port,
c.Rmr.ReadyIntervalSec,
c.Rnib.MaxRnibConnectionAttempts,
c.Rnib.RnibRetryIntervalMs,
- c.ResourceStatusParams.EnableResourceStatus,
- c.ResourceStatusParams.PartialSuccessAllowed,
- c.ResourceStatusParams.PrbPeriodic,
- c.ResourceStatusParams.TnlLoadIndPeriodic,
- c.ResourceStatusParams.HwLoadIndPeriodic,
- c.ResourceStatusParams.AbsStatusPeriodic,
- c.ResourceStatusParams.RsrpMeasurementPeriodic,
- c.ResourceStatusParams.CsiPeriodic,
-
- c.ResourceStatusParams.PeriodicityMs,
- c.ResourceStatusParams.PeriodicityRsrpMeasurementMs,
- c.ResourceStatusParams.PeriodicityCsiMs,
)
}
assert.Equal(t, 3, config.Rnib.MaxRnibConnectionAttempts)
assert.Equal(t, 10, config.Rnib.RnibRetryIntervalMs)
-
- assert.Equal(t, true, config.ResourceStatusParams.EnableResourceStatus)
- assert.Equal(t, true, config.ResourceStatusParams.PrbPeriodic)
- assert.Equal(t, true, config.ResourceStatusParams.TnlLoadIndPeriodic)
- assert.Equal(t, true, config.ResourceStatusParams.HwLoadIndPeriodic)
- assert.Equal(t, true, config.ResourceStatusParams.AbsStatusPeriodic)
- assert.Equal(t, true, config.ResourceStatusParams.RsrpMeasurementPeriodic)
- assert.Equal(t, true, config.ResourceStatusParams.CsiPeriodic)
-
- /*assert.Equal(t, 1, config.ResourceStatusParams.PeriodicityMs)
- assert.Equal(t, 120, config.ResourceStatusParams.PeriodicityRsrpMeasurementMs)
- assert.Equal(t, 5, config.ResourceStatusParams.PeriodicityCsiMs)*/
-
}
func TestParseConfigurationFileNotFoundFailure(t *testing.T) {
func TestRmrConfigNotFoundFailure(t *testing.T) {
yamlMap := map[string]interface{}{
- "logging": map[string]interface{}{"logLevel": "info"},
- "http": map[string]interface{}{"port": 631},
- "resourceStatusParams": map[string]interface{}{"enableResourceStatus": true, "periodicityCsiMs": 5},
- "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
+ "logging": map[string]interface{}{"logLevel": "info"},
+ "http": map[string]interface{}{"port": 631},
+ "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
}
cleanUp := prepareTempConfigForTest(t, yamlMap)
defer cleanUp()
func TestLoggingConfigNotFoundFailure(t *testing.T) {
yamlMap := map[string]interface{}{
- "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
- "http": map[string]interface{}{"port": 631},
+ "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
+ "http": map[string]interface{}{"port": 631},
"resourceStatusParams": map[string]interface{}{"enableResourceStatus": true, "periodicityCsiMs": 5},
- "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
+ "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
}
cleanUp := prepareTempConfigForTest(t, yamlMap)
defer cleanUp()
func TestHttpConfigNotFoundFailure(t *testing.T) {
yamlMap := map[string]interface{}{
- "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
- "logging": map[string]interface{}{"logLevel": "info"},
+ "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
+ "logging": map[string]interface{}{"logLevel": "info"},
"resourceStatusParams": map[string]interface{}{"enableResourceStatus": true, "periodicityCsiMs": 5},
- "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
+ "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
}
cleanUp := prepareTempConfigForTest(t, yamlMap)
defer cleanUp()
func TestRnibConfigNotFoundFailure(t *testing.T) {
yamlMap := map[string]interface{}{
- "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
- "logging": map[string]interface{}{"logLevel": "info"},
- "http": map[string]interface{}{"port": 631},
- "resourceStatusParams": map[string]interface{}{"enableResourceStatus": true, "periodicityCsiMs": 5},
+ "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
+ "logging": map[string]interface{}{"logLevel": "info"},
+ "http": map[string]interface{}{"port": 631},
}
cleanUp := prepareTempConfigForTest(t, yamlMap)
defer cleanUp()
assert.EqualError(t, cErr, "#configuration.fillRnibConfig - failed to fill RNib configuration: The entry 'rnib' not found\n")
}
-func TestResourceStatusParamsConfigNotFoundFailure(t *testing.T) {
-
- yamlMap := map[string]interface{}{
- "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
- "logging": map[string]interface{}{"logLevel": "info"},
- "http": map[string]interface{}{"port": 631},
- "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
- }
- cleanUp := prepareTempConfigForTest(t, yamlMap)
- defer cleanUp()
-
- _, cErr := ParseConfiguration()
- assert.EqualError(t, cErr, "#configuration.fillResourceStatusParamsConfig - failed to fill resourceStatusParams configuration: The entry 'resourceStatusParams' not found\n")
-}
-
-func TestCharacteristicsConfigInvalidPeriodicityMs(t *testing.T) {
-
- yamlMap := map[string]interface{}{
- "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
- "logging": map[string]interface{}{"logLevel": "info"},
- "http": map[string]interface{}{"port": 631},
- "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
- "resourceStatusParams": map[string]interface{}{"enableResourceStatus": true, "periodicityMs": 50, "periodicityRsrpMeasurementMs": 480, "periodicityCsiMs": 20},
- }
- cleanUp := prepareTempConfigForTest(t, yamlMap)
- defer cleanUp()
-
- _, cErr := ParseConfiguration()
- assert.Error(t, cErr)
-}
-
-func TestResourceStatusParamsConfigInvalidPeriodicityRsrpMeasurementMs(t *testing.T) {
-
- yamlMap := map[string]interface{}{
- "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
- "logging": map[string]interface{}{"logLevel": "info"},
- "http": map[string]interface{}{"port": 631},
- "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
- "resourceStatusParams": map[string]interface{}{"enableResourceStatus": true, "periodicityMs": 1000, "periodicityRsrpMeasurementMs": 50, "periodicityCsiMs": 20},
- }
- cleanUp := prepareTempConfigForTest(t, yamlMap)
- defer cleanUp()
-
- _, cErr := ParseConfiguration()
- assert.Error(t, cErr)
-}
-
-func TestResourceStatusParamsConfigInvalidPeriodicityCsiMs(t *testing.T) {
-
- yamlMap := map[string]interface{}{
- "rmr": map[string]interface{}{"port": 6942, "maxMsgSize": 4096},
- "logging": map[string]interface{}{"logLevel": "info"},
- "http": map[string]interface{}{"port": 631},
- "rnib": map[string]interface{}{"maxRnibConnectionAttempts": 3, "rnibRetryIntervalMs": 10},
- "resourceStatusParams": map[string]interface{}{"enableResourceStatus": true, "periodicityMs": 1000, "periodicityRsrpMeasurementMs": 480, "periodicityCsiMs": 50},
- }
- cleanUp := prepareTempConfigForTest(t, yamlMap)
- defer cleanUp()
-
- _, cErr := ParseConfiguration()
- assert.Error(t, cErr)
-}
-
func TestConfigurationString(t *testing.T) {
config, err := ParseConfiguration()
if err != nil {
assert.Contains(t, str, "http")
assert.Contains(t, str, "rmr")
assert.Contains(t, str, "rnib")
- assert.Contains(t, str, "resourceStatusParams")
}
func prepareTempConfigForTest(t *testing.T, yamlMap map[string]interface{}) func() {
package controllers
-type IController interface {
-}
-/*
import (
"encoding/json"
"io"
)
type IController interface {
+ ResourceStatus(writer http.ResponseWriter, r *http.Request)
}
type Controller struct {
}
}
+func (c *Controller) ResourceStatus(writer http.ResponseWriter, r *http.Request) {
+ c.logger.Infof("[Client -> RSM] #Controller.ResourceStatus - request: %v", c.prettifyRequest(r))
+
+ request := models.ResourceStatusRequest{}
+
+ if !c.extractJsonBody(r, &request, writer) {
+ return
+ }
+
+ c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ResourceStatusRequest, request, true)
+}
+
func (c *Controller) extractJsonBody(r *http.Request, request models.Request, writer http.ResponseWriter) bool {
defer r.Body.Close()
body, err := ioutil.ReadAll(io.LimitReader(r.Body, LimitRequest))
return
}
- response, err := (*handler).Handle(request)
+ err = handler.Handle(request)
if err != nil {
c.handleErrorResponse(err, writer)
return
}
- if response == nil {
- writer.WriteHeader(http.StatusNoContent)
- c.logger.Infof("[RSM -> Client] #Controller.handleRequest - status response: %v", http.StatusNoContent)
- return
- }
-
- result, err := response.Marshal()
-
- if err != nil {
- c.handleErrorResponse(err, writer)
- return
- }
-
- c.logger.Infof("[RSM -> Client] #Controller.handleRequest - response: %s", result)
- writer.Header().Set("Content-Type", "application/json")
- writer.Write([]byte(result))
+ writer.WriteHeader(http.StatusNoContent)
+ c.logger.Infof("[RSM -> Client] #Controller.handleRequest - status response: %v", http.StatusNoContent)
}
func (c *Controller) validateRequestHeader(header *http.Header) error {
e2Error, _ := err.(*rsmerrors.RmrError)
errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
httpError = http.StatusInternalServerError
+ case *rsmerrors.RsmError:
+ e2Error, _ := err.(*rsmerrors.RsmError)
+ errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
+ httpError = http.StatusInternalServerError
case *rsmerrors.ResourceNotFoundError:
e2Error, _ := err.(*rsmerrors.ResourceNotFoundError)
errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
if err != nil {
c.logger.Errorf("#Controller.handleErrorResponse - Cannot send response. writer:%v", writer)
}
-}*/
-/*
+}
func (c *Controller) prettifyRequest(request *http.Request) string {
dump, _ := httputil.DumpRequest(request, true)
requestPrettyPrint := strings.Replace(string(dump), "\r\n", " ", -1)
return strings.Replace(requestPrettyPrint, "\n", "", -1)
-}
-*/
\ No newline at end of file
+}
\ No newline at end of file
package controllers
-/*
import (
"encoding/json"
"fmt"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"rsm/configuration"
+ "rsm/enums"
+ "rsm/logger"
"rsm/mocks"
"rsm/models"
"rsm/providers/httpmsghandlerprovider"
"rsm/rsmerrors"
- "rsm/tests/testhelper"
+ "rsm/services"
+ "rsm/tests"
+ "strings"
"testing"
)
-func setupControllerTest(t *testing.T) (*Controller, *mocks.RnibReaderMock, *mocks.RmrMessengerMock) {
- config := configuration.ParseConfiguration()
+func setupControllerTest(t *testing.T) (*Controller, *mocks.RnibReaderMock, *mocks.RsmReaderMock, *mocks.RsmWriterMock, *mocks.ResourceStatusServiceMock) {
+ log, err := logger.InitLogger(logger.DebugLevel)
+ if err != nil {
+ t.Errorf("#... - failed to initialize logger, error: %s", err)
+ }
- rmrMessengerMock := &mocks.RmrMessengerMock{}
- readerMock := &mocks.RnibReaderMock{}
- rnibDataService, rmrSender, log := testhelper.InitTestCase(t)
- handlerProvider := httpmsghandlerprovider.NewRequestHandlerProvider(log, rmrSender, config, rnibDataService)
+ config, err := configuration.ParseConfiguration()
+ if err != nil {
+ t.Errorf("#... - failed to parse configuration error: %s", err)
+ }
+
+ resourceStatusServiceMock := &mocks.ResourceStatusServiceMock{}
+ rnibReaderMock := &mocks.RnibReaderMock{}
+ rsmReaderMock := &mocks.RsmReaderMock{}
+ rsmWriterMock := &mocks.RsmWriterMock{}
+
+ rnibDataService := services.NewRnibDataService(log, config, rnibReaderMock, rsmReaderMock, rsmWriterMock)
+ handlerProvider := httpmsghandlerprovider.NewRequestHandlerProvider(log, rnibDataService, resourceStatusServiceMock)
controller := NewController(log, handlerProvider)
- return controller, readerMock, rmrMessengerMock
+ return controller, rnibReaderMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock
+}
+
+func TestResourceStatusInvalidBody(t *testing.T) {
+ controller, _, _, _ , _:= setupControllerTest(t)
+
+ header := http.Header{}
+ header.Set("Content-Type", "application/json")
+ httpRequest, _ := http.NewRequest("PUT", "http://localhost:4800/v1/general/resourcestatus", strings.NewReader("{}{}"))
+ httpRequest.Header = header
+
+ writer := httptest.NewRecorder()
+ controller.ResourceStatus(writer, httpRequest)
+
+ var errorResponse = parseJsonRequest(t, writer.Body)
+
+ assert.Equal(t, http.StatusBadRequest, writer.Result().StatusCode)
+ assert.Equal(t, rsmerrors.NewInvalidJsonError().Code, errorResponse.Code)
+}
+
+func TestResourceStatusSuccess(t *testing.T) {
+ controller, readerMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock := setupControllerTest(t)
+
+ cellId1 := "02f829:0007ab00"
+ cellId2 := "02f829:0007ab50"
+ nodebInfo := &entities.NodebInfo{
+ RanName: tests.RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ Configuration: &entities.NodebInfo_Enb{
+ Enb: &entities.Enb{
+ ServedCells: []*entities.ServedCellInfo{{CellId: cellId1}, {CellId: cellId2}},
+ },
+ },
+ }
+ var nbIdentityList []*entities.NbIdentity
+ config := tests.GetRsmGeneralConfiguration(true)
+
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, nil)
+ readerMock.On("GetNodeb", tests.RanName).Return(nodebInfo)
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
+
+ header := http.Header{}
+ header.Set("Content-Type", "application/json")
+ httpRequest, _ := http.NewRequest("PUT", "http://localhost:4800/v1/general/resourcestatus", strings.NewReader("{\"enableResourceStatus\":true}"))
+ httpRequest.Header = header
+
+ writer := httptest.NewRecorder()
+ controller.ResourceStatus(writer, httpRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetListEnbIds", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
+
+ assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode)
+}
+
+func TestResourceStatusFail(t *testing.T) {
+
+ controller, readerMock, rsmReaderMock, _, resourceStatusServiceMock := setupControllerTest(t)
+
+ rnibErr := &rsmerrors.RnibDbError{}
+
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(tests.GetRsmGeneralConfiguration(true), rnibErr)
+
+ header := http.Header{}
+ header.Set("Content-Type", "application/json")
+ httpRequest, _ := http.NewRequest("PUT", "http://localhost:4800/v1/general/resourcestatus", strings.NewReader("{\"enableResourceStatus\":true}"))
+ httpRequest.Header = header
+
+ writer := httptest.NewRecorder()
+ controller.ResourceStatus(writer, httpRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetListEnbIds", 0)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
+
+ assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
}
func TestHeaderValidationFailed(t *testing.T) {
- controller, _, _ := setupControllerTest(t)
+ controller, _, _ ,_ , _:= setupControllerTest(t)
writer := httptest.NewRecorder()
header := &http.Header{}
assert.Equal(t, errorResponse.Code, err.Code)
assert.Equal(t, errorResponse.Message, err.Message)
}
-*/
-/*func TestHandleInternalError(t *testing.T) {
- controller, _, _ := setupControllerTest(t)
+
+func TestHandleInternalError(t *testing.T) {
+ controller, _, _,_ ,_ := setupControllerTest(t)
writer := httptest.NewRecorder()
err := rsmerrors.NewInternalError()
assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
assert.Equal(t, errorResponse.Code, err.Code)
assert.Equal(t, errorResponse.Message, err.Message)
-}*/
+}
-/*func TestValidateHeadersSuccess(t *testing.T) {
- controller, _, _ := setupControllerTest(t)
+func TestValidateHeadersSuccess(t *testing.T) {
+ controller, _, _,_ ,_ := setupControllerTest(t)
header := http.Header{}
header.Set("Content-Type", "application/json")
assert.Nil(t, result)
}
-*/
-/*func parseJsonRequest(t *testing.T, r io.Reader) models.ErrorResponse {
+
+func parseJsonRequest(t *testing.T, r io.Reader) models.ErrorResponse {
var errorResponse models.ErrorResponse
body, err := ioutil.ReadAll(r)
json.Unmarshal(body, &errorResponse)
return errorResponse
-}*/
-/*
+}
+
func TestHandleErrorResponse(t *testing.T) {
- controller, _, _ := setupControllerTest(t)
+ controller, _, _ ,_ , _:= setupControllerTest(t)
writer := httptest.NewRecorder()
controller.handleErrorResponse(rsmerrors.NewRnibDbError(), writer)
writer = httptest.NewRecorder()
controller.handleErrorResponse(fmt.Errorf("ErrorError"), writer)
assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
-}
-*/
\ No newline at end of file
+
+ writer = httptest.NewRecorder()
+ controller.handleErrorResponse(rsmerrors.NewRsmError(2), writer)
+ assert.Equal(t, http.StatusInternalServerError, writer.Result().StatusCode)
+}
\ No newline at end of file
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
- "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
"github.com/stretchr/testify/assert"
"net"
"net/http"
if err != nil {
t.Errorf("#... - failed to parse configuration error: %s", err)
}
- readerMock := &mocks.RnibReaderMock{}
- rnibReaderProvider := func() reader.RNibReader {
- return readerMock
- }
- rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider)
- return rnibDataService, readerMock
+ rnibReaderMock := &mocks.RnibReaderMock{}
+ rsmReaderMock := &mocks.RsmReaderMock{}
+ rsmWriterMock := &mocks.RsmWriterMock{}
+
+ rnibDataService := services.NewRnibDataService(logger, config, rnibReaderMock, rsmReaderMock, rsmWriterMock)
+ return rnibDataService, rnibReaderMock
}
func TestNewRequestController(t *testing.T) {
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 converters
+
+// #cgo CFLAGS: -I../asn1codec/inc/ -I../asn1codec/e2ap_engine/
+// #cgo LDFLAGS: -L ../asn1codec/lib/ -L../asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
+// #include <asn1codec_utils.h>
+// #include <resource_status_response_wrapper.h>
+import "C"
+import (
+ "fmt"
+ "rsm/models"
+ "unsafe"
+)
+
+type ResourceStatusFailureConverter struct {
+ X2apPduUnpacker
+}
+
+func NewResourceStatusFailureConverter(unpacker X2apPduUnpacker) ResourceStatusFailureConverter {
+ return ResourceStatusFailureConverter{unpacker}
+}
+
+func convertCompleteFailureCauseInformation(completeFailureCauseInformation_List *C.CompleteFailureCauseInformation_List_t) ([]*models.MeasurementInitiationResult, error) {
+ var measurementInitiationResults []*models.MeasurementInitiationResult
+
+ count := int(completeFailureCauseInformation_List.list.count)
+ if count < 1 || count > maxCellineNB {
+ return nil, fmt.Errorf("invalid number of complete failure cause information elements, %d", count)
+ }
+ completeFailureCauseInformation_ItemIEs_slice := (*[1 << 30]*C.CompleteFailureCauseInformation_ItemIEs_t)(unsafe.Pointer(completeFailureCauseInformation_List.list.array))[:count:count]
+ for _, itemIE := range completeFailureCauseInformation_ItemIEs_slice {
+
+ switch itemIE.value.present {
+ case C.CompleteFailureCauseInformation_ItemIEs__value_PR_CompleteFailureCauseInformation_Item:
+ item := (*C.CompleteFailureCauseInformation_Item_t)(unsafe.Pointer(&itemIE.value.choice[0]))
+ measurementInitiationResult := models.MeasurementInitiationResult{CellId: buildCellId(item.cell_ID)}
+ if err:=convertMeasurementFailureCauses(&item.measurementFailureCause_List, &measurementInitiationResult); err != nil {
+ return nil, err
+ }
+ measurementInitiationResults = append(measurementInitiationResults, &measurementInitiationResult)
+ }
+ }
+
+ return measurementInitiationResults, nil
+}
+
+func convertResourceFailureIEs(resourceStatusFailure *C.ResourceStatusFailure_t, response *models.ResourceStatusResponse) error {
+ count := int(resourceStatusFailure.protocolIEs.list.count)
+ resourceStatusFailure_IEs_slice := (*[1 << 30]*C.ResourceStatusFailure_IEs_t)(unsafe.Pointer(resourceStatusFailure.protocolIEs.list.array))[:count:count]
+ for _, resourceStatusFailure_IEs := range resourceStatusFailure_IEs_slice {
+ switch resourceStatusFailure_IEs.value.present {
+ case C.ResourceStatusFailure_IEs__value_PR_Measurement_ID:
+ measurement_ID := (*C.Measurement_ID_t)(unsafe.Pointer(&resourceStatusFailure_IEs.value.choice[0]))
+ if resourceStatusFailure_IEs.id == C.ProtocolIE_ID_id_ENB1_Measurement_ID {
+ response.ENB1_Measurement_ID = int64(*measurement_ID)
+ }
+ if resourceStatusFailure_IEs.id == C.ProtocolIE_ID_id_ENB2_Measurement_ID {
+ response.ENB2_Measurement_ID = int64(*measurement_ID)
+ }
+ case C.ResourceStatusFailure_IEs__value_PR_CriticalityDiagnostics:
+ /*ignored*/
+ case C.ResourceStatusFailure_IEs__value_PR_Cause:
+ /*ignored*/
+ case C.ResourceStatusFailure_IEs__value_PR_CompleteFailureCauseInformation_List:
+ measurementInitiationResults, err := convertCompleteFailureCauseInformation((*C.CompleteFailureCauseInformation_List_t)(unsafe.Pointer(&resourceStatusFailure_IEs.value.choice[0])))
+ if err != nil {
+ return err
+ }
+ response.MeasurementInitiationResults = measurementInitiationResults
+ }
+ }
+ return nil
+}
+
+func convertResourceStatusFailure(pdu *C.E2AP_PDU_t) (*models.ResourceStatusResponse, error) {
+ response := models.ResourceStatusResponse{}
+
+ if pdu.present != C.E2AP_PDU_PR_unsuccessfulOutcome {
+ return &response, fmt.Errorf("unexpected PDU, %d", int(pdu.present))
+ }
+
+ //dereference a union of pointers (C union is represented as a byte array with the size of the largest member)
+ unsuccessfulOutcome := *(**C.UnsuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
+ if unsuccessfulOutcome == nil || unsuccessfulOutcome.value.present != C.UnsuccessfulOutcome__value_PR_ResourceStatusFailure {
+ return &response, fmt.Errorf("unexpected PDU - not a resource status failure")
+ }
+
+ resourceStatusFailure := (*C.ResourceStatusFailure_t)(unsafe.Pointer(&unsuccessfulOutcome.value.choice[0]))
+ if resourceStatusFailure.protocolIEs.list.count == 0 {
+ return &response, fmt.Errorf("unexpected PDU - no protocolIEs found")
+ }
+
+ if err := convertResourceFailureIEs(resourceStatusFailure, &response); err != nil {
+ return &response, err
+ }
+
+ return &response, nil
+}
+
+// Convert pdu to public ResourceStatusResponse
+func (r ResourceStatusFailureConverter) Convert(packedBuf []byte) (*models.ResourceStatusResponse, error) {
+ pdu, err := r.UnpackX2apPdu(packedBuf)
+ if err != nil {
+ return nil, err
+ }
+
+ defer C.delete_pdu(pdu)
+ return convertResourceStatusFailure(pdu)
+}
--- /dev/null
+/*******************************************************************************
+ *
+ * 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 converters
+
+import (
+ "fmt"
+ "rsm/e2pdus"
+ "rsm/logger"
+ "strings"
+ "testing"
+)
+
+/*
+ * Unpack a response returned from RAN.
+ * Verify it matches the want pdu.
+ */
+
+func TestResourceStatusFailureConverter(t *testing.T) {
+ logger, _ := logger.InitLogger(logger.DebugLevel)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ rsFailureConverter := NewResourceStatusFailureConverter(unpacker)
+
+ var testCases = []struct {
+ response string
+ packedPdu string
+ }{
+ {
+ response: "ENB1_Measurement_ID: 15, ENB2_Measurement_ID: 13, MeasurementInitiationResults:[ CellId: 02f829:0007ab50, MeasurementFailureCauses: [ MeasurementFailedReportCharacteristics: 00000007 ] ]",
+ /*
+ UnsuccessfulOutcome ::= {
+ procedureCode: 9
+ criticality: 0 (reject)
+ value: ResourceStatusFailure ::= {
+ protocolIEs: ProtocolIE-Container ::= {
+ ResourceStatusFailure-IEs ::= {
+ id: 39
+ criticality: 0 (reject)
+ value: 15
+ }
+ ResourceStatusFailure-IEs ::= {
+ id: 40
+ criticality: 0 (reject)
+ value: 13
+ }
+ ResourceStatusFailure-IEs ::= {
+ id: 5
+ criticality: 1 (ignore)
+ value: 1 (hardware-failure)
+ }
+ ResourceStatusFailure-IEs ::= {
+ id: 68
+ criticality: 1 (ignore)
+ value: CompleteFailureCauseInformation-List ::= {
+ ProtocolIE-Single-Container ::= {
+ id: 69
+ criticality: 1 (ignore)
+ value: CompleteFailureCauseInformation-Item ::= {
+ cell-ID: ECGI ::= {
+ pLMN-Identity: 02 F8 29
+ eUTRANcellIdentifier: 00 07 AB 50 (4 bits unused)
+ }
+ measurementFailureCause-List: MeasurementFailureCause-List ::= {
+ ProtocolIE-Single-Container ::= {
+ id: 67
+ criticality: 1 (ignore)
+ value: MeasurementFailureCause-Item ::= {
+ measurementFailedReportCharacteristics: 00 00 00 07
+ cause: 0 (transfer-syntax-error)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }*/
+
+ packedPdu: "400900320000040027000300000e0028000300000c00054001620044401800004540130002f8290007ab500000434006000000000740",
+ },
+ {
+ response: "ENB1_Measurement_ID: 1, ENB2_Measurement_ID: 74, MeasurementInitiationResults:[ ]",
+ /*
+ UnsuccessfulOutcome ::= {
+ procedureCode: 9
+ criticality: 0 (reject)
+ value: ResourceStatusFailure ::= {
+ protocolIEs: ProtocolIE-Container ::= {
+ ResourceStatusFailure-IEs ::= {
+ id: 39
+ criticality: 0 (reject)
+ value: 1
+ }
+ ResourceStatusFailure-IEs ::= {
+ id: 40
+ criticality: 0 (reject)
+ value: 74
+ }
+ ResourceStatusFailure-IEs ::= {
+ id: 5
+ criticality: 1 (ignore)
+ value: 21 (unspecified)
+ }
+ }
+ }
+ }
+ */
+ packedPdu: "400900170000030027000300000000280003000049000540020a80",
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.packedPdu, func(t *testing.T) {
+ var payload []byte
+
+ _, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
+ if err != nil {
+ t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+ }
+
+ response, err := rsFailureConverter.Convert(payload)
+ if err != nil {
+ t.Errorf("want: success, got: unpack failed. Error: %v\n", err)
+ }
+
+ got := response.String()
+ if len(tc.response) != len(got) {
+ t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", tc.response, response)
+ }
+ if strings.Compare(tc.response, got) != 0 {
+ t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", tc.response, got)
+ }
+ })
+ }
+}
+
+/*unpacking error*/
+
+func TestResourceStatusFailureConverterError(t *testing.T) {
+ logger, _ := logger.InitLogger(logger.InfoLevel)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ rsFailureConverter := NewResourceStatusFailureConverter(unpacker)
+ wantError := "unpacking error: #src/asn1codec_utils.c.unpack_pdu_aux - Failed to decode E2AP-PDU (consumed 0), error = 0 Success"
+ //--------------------2006002a
+ inputPayloadAsStr := "2006002b000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"
+ var payload []byte
+ _, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
+ if err != nil {
+ t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+ }
+
+ _, err = rsFailureConverter.Convert(payload)
+ if err != nil {
+ if 0 != strings.Compare(fmt.Sprintf("%s", err), wantError) {
+ t.Errorf("want failure: %s, got: %s", wantError, err)
+ }
+ } else {
+ t.Errorf("want failure: %s, got: success", wantError)
+
+ }
+}
+
+func TestResourceStatusFailureConverterPduOfSuccess(t *testing.T) {
+ logger, _ := logger.InitLogger(logger.InfoLevel)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ rsFailureConverter := NewResourceStatusFailureConverter(unpacker)
+ wantError := "unexpected PDU, 2"
+ inputPayloadAsStr := "200900220000030027000300000e0028000300000c0041400d00004240080002f8290007ab50"
+ var payload []byte
+ _, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
+ if err != nil {
+ t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+ }
+
+ _, err = rsFailureConverter.Convert(payload)
+ if err != nil {
+ if 0 != strings.Compare(fmt.Sprintf("%s", err), wantError) {
+ t.Errorf("want failure: %s, got: %s", wantError, err)
+ }
+ } else {
+ t.Errorf("want failure: %s, got: success", wantError)
+
+ }
+}
+
+func TestResourceStatusFailureConverterWrongPdu(t *testing.T) {
+ logger, _ := logger.InitLogger(logger.InfoLevel)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ rsFailureConverter := NewResourceStatusFailureConverter(unpacker)
+ wantError := "unexpected PDU - not a resource status failure"
+ inputPayloadAsStr := "4006001a0000030005400200000016400100001140087821a00000008040"
+ var payload []byte
+ _, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
+ if err != nil {
+ t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+ }
+
+ _, err = rsFailureConverter.Convert(payload)
+ if err != nil {
+ if 0 != strings.Compare(fmt.Sprintf("%s", err), wantError) {
+ t.Errorf("want failure: %s, got: %s", wantError, err)
+ }
+ } else {
+ t.Errorf("want failure: %s, got: success", wantError)
+
+ }
+}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 converters
+
+// #cgo CFLAGS: -I../asn1codec/inc/ -I../asn1codec/e2ap_engine/
+// #cgo LDFLAGS: -L ../asn1codec/lib/ -L../asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
+// #include <asn1codec_utils.h>
+// #include <resource_status_response_wrapper.h>
+import "C"
+import (
+ "fmt"
+ "rsm/models"
+ "unsafe"
+)
+
+const (
+ maxCellineNB = 256
+ maxFailedMeasObjects = 32
+)
+
+type IResourceStatusResponseConverter interface {
+ Convert(packedBuf []byte) (*models.ResourceStatusResponse, error)
+ UnpackX2apPduAsString(packedBuf []byte, maxMessageBufferSize int) (string, error)
+}
+
+type ResourceStatusResponseConverter struct {
+ X2apPduUnpacker
+}
+
+func NewResourceStatusResponseConverter(unpacker X2apPduUnpacker) ResourceStatusResponseConverter {
+ return ResourceStatusResponseConverter{unpacker}
+}
+
+func buildCellId(cellId C.ECGI_t) string {
+ plmnId := C.GoBytes(unsafe.Pointer(cellId.pLMN_Identity.buf), C.int(cellId.pLMN_Identity.size))
+ eutranCellIdentifier := C.GoBytes(unsafe.Pointer(cellId.eUTRANcellIdentifier.buf), C.int(cellId.eUTRANcellIdentifier.size))
+ return fmt.Sprintf("%x:%x", plmnId, eutranCellIdentifier)
+}
+
+func convertMeasurementFailureCauses(measurementFailureCause_List *C.MeasurementFailureCause_List_t, measurementInitiationResult *models.MeasurementInitiationResult) error {
+ var MeasurementFailureCauses []*models.MeasurementFailureCause
+
+ count := int(measurementFailureCause_List.list.count)
+ if count < 1 || count > maxFailedMeasObjects {
+ return fmt.Errorf("invalid number of failure cause elements, %d", int(count))
+ }
+
+ measurementFailureCause_ItemIEs_slice := (*[1 << 30]*C.MeasurementFailureCause_ItemIEs_t)(unsafe.Pointer(measurementFailureCause_List.list.array))[:count:count]
+ for _, itemIE := range measurementFailureCause_ItemIEs_slice {
+ switch itemIE.value.present {
+ case C.MeasurementFailureCause_ItemIEs__value_PR_MeasurementFailureCause_Item:
+ item := (*C.MeasurementFailureCause_Item_t)(unsafe.Pointer(&itemIE.value.choice[0]))
+ measurementFailedReportCharacteristics := C.GoBytes(unsafe.Pointer(item.measurementFailedReportCharacteristics.buf), C.int(item.measurementFailedReportCharacteristics.size))
+ measurementFailureCause := models.MeasurementFailureCause{MeasurementFailedReportCharacteristics: measurementFailedReportCharacteristics}
+ MeasurementFailureCauses = append(MeasurementFailureCauses, &measurementFailureCause)
+ /*Cause ignored - only need to know that the request failed and, possibly, which report characteristics failed*/
+ }
+ measurementInitiationResult.MeasurementFailureCauses = MeasurementFailureCauses
+ }
+
+ return nil
+}
+
+func convertMeasurementInitiationResult(measurementInitiationResult_List *C.MeasurementInitiationResult_List_t) ([]*models.MeasurementInitiationResult, error) {
+ var measurementInitiationResults []*models.MeasurementInitiationResult
+
+ count := int(measurementInitiationResult_List.list.count)
+ if count < 1 || count > maxCellineNB {
+ return nil, fmt.Errorf("invalid number of measurement initiation result elements, %d", count)
+ }
+ measurementInitiationResult_ItemIEs_slice := (*[1 << 30]*C.MeasurementInitiationResult_ItemIEs_t)(unsafe.Pointer(measurementInitiationResult_List.list.array))[:count:count]
+ for _, itemIE := range measurementInitiationResult_ItemIEs_slice {
+ switch itemIE.value.present {
+ case C.MeasurementInitiationResult_ItemIEs__value_PR_MeasurementInitiationResult_Item:
+ item := (*C.MeasurementInitiationResult_Item_t)(unsafe.Pointer(&itemIE.value.choice[0]))
+ measurementInitiationResult := models.MeasurementInitiationResult{CellId: buildCellId(item.cell_ID)}
+ if item.measurementFailureCause_List != nil {
+ if err:= convertMeasurementFailureCauses(item.measurementFailureCause_List, &measurementInitiationResult); err != nil {
+ return nil, err
+ }
+ }
+ measurementInitiationResults = append(measurementInitiationResults, &measurementInitiationResult)
+ }
+
+ }
+
+ return measurementInitiationResults, nil
+}
+
+func convertResourceStatusIEs(resourceStatusResponse *C.ResourceStatusResponse_t, response *models.ResourceStatusResponse) error {
+ count := int(resourceStatusResponse.protocolIEs.list.count)
+ resourceStatusResponse_IEs_slice := (*[1 << 30]*C.ResourceStatusResponse_IEs_t)(unsafe.Pointer(resourceStatusResponse.protocolIEs.list.array))[:count:count]
+ for _, resourceStatusResponse_IEs := range resourceStatusResponse_IEs_slice {
+ switch resourceStatusResponse_IEs.value.present {
+ case C.ResourceStatusResponse_IEs__value_PR_Measurement_ID:
+ measurement_ID := (*C.Measurement_ID_t)(unsafe.Pointer(&resourceStatusResponse_IEs.value.choice[0]))
+ if resourceStatusResponse_IEs.id == C.ProtocolIE_ID_id_ENB1_Measurement_ID {
+ response.ENB1_Measurement_ID = int64(*measurement_ID)
+ }
+ if resourceStatusResponse_IEs.id == C.ProtocolIE_ID_id_ENB2_Measurement_ID {
+ response.ENB2_Measurement_ID = int64(*measurement_ID)
+ }
+ case C.ResourceStatusResponse_IEs__value_PR_CriticalityDiagnostics:
+ /*ignored*/
+
+ case C.ResourceStatusResponse_IEs__value_PR_MeasurementInitiationResult_List:
+ measurementInitiationResults, err := convertMeasurementInitiationResult((*C.MeasurementInitiationResult_List_t)(unsafe.Pointer(&resourceStatusResponse_IEs.value.choice[0])))
+ if err != nil {
+ return err
+ }
+ response.MeasurementInitiationResults = measurementInitiationResults
+ }
+ }
+ return nil
+}
+
+func convertResourceStatusResponse(pdu *C.E2AP_PDU_t) (*models.ResourceStatusResponse, error) {
+ response := models.ResourceStatusResponse{}
+
+ if pdu.present != C.E2AP_PDU_PR_successfulOutcome {
+ return &response, fmt.Errorf("unexpected PDU, %d", int(pdu.present))
+ }
+
+ //dereference a union of pointers (C union is represented as a byte array with the size of the largest member)
+ successfulOutcome := *(**C.SuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
+ if successfulOutcome == nil || successfulOutcome.value.present != C.SuccessfulOutcome__value_PR_ResourceStatusResponse {
+ return &response, fmt.Errorf("unexpected PDU - not a resource status response")
+ }
+
+ resourceStatusResponse := (*C.ResourceStatusResponse_t)(unsafe.Pointer(&successfulOutcome.value.choice[0]))
+ if resourceStatusResponse.protocolIEs.list.count == 0 {
+ return &response, fmt.Errorf("unexpected PDU - no protocolIEs found")
+ }
+
+ if err := convertResourceStatusIEs(resourceStatusResponse, &response); err != nil {
+ return &response, err
+ }
+
+ return &response, nil
+}
+
+// Convert pdu to public ResourceStatusResponse
+func (r ResourceStatusResponseConverter) Convert(packedBuf []byte) (*models.ResourceStatusResponse, error) {
+ pdu, err := r.UnpackX2apPdu(packedBuf)
+ if err != nil {
+ return nil, err
+ }
+
+ defer C.delete_pdu(pdu)
+ return convertResourceStatusResponse(pdu)
+}
--- /dev/null
+/*******************************************************************************
+ *
+ * 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 converters
+
+import (
+ "fmt"
+ "rsm/e2pdus"
+ "rsm/logger"
+ "strings"
+ "testing"
+)
+
+/*
+ * Unpack a response returned from RAN.
+ * Verify it matches the want pdu.
+ */
+
+func TestResourceStatusResponseConverter(t *testing.T) {
+ logger, _ := logger.InitLogger(logger.DebugLevel)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ rsConverters := NewResourceStatusResponseConverter(unpacker)
+
+ var testCases = []struct {
+ response string
+ packedPdu string
+ }{
+ {
+ response: "ENB1_Measurement_ID: 15, ENB2_Measurement_ID: 13, MeasurementInitiationResults:[ CellId: 02f829:0007ab50, MeasurementFailureCauses: [ ] ]",
+ /*
+ SuccessfulOutcome ::= {
+ procedureCode: 9
+ criticality: 0 (reject)
+ value: ResourceStatusResponse ::= {
+ protocolIEs: ProtocolIE-Container ::= {
+ ResourceStatusResponse-IEs ::= {
+ id: 39
+ criticality: 0 (reject)
+ value: 15
+ }
+ ResourceStatusResponse-IEs ::= {
+ id: 40
+ criticality: 0 (reject)
+ value: 13
+ }
+ ResourceStatusResponse-IEs ::= {
+ id: 65
+ criticality: 1 (ignore)
+ value: MeasurementInitiationResult-List ::= {
+ ProtocolIE-Single-Container ::= {
+ id: 66
+ criticality: 1 (ignore)
+ value: MeasurementInitiationResult-Item ::= {
+ cell-ID: ECGI ::= {
+ pLMN-Identity: 02 F8 29
+ eUTRANcellIdentifier: 00 07 AB 50 (4 bits unused)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ */
+
+ packedPdu: "200900220000030027000300000e0028000300000c0041400d00004240080002f8290007ab50",
+ },
+ {response: "ENB1_Measurement_ID: 1, ENB2_Measurement_ID: 75, MeasurementInitiationResults:[ CellId: 133023:02b030a0, MeasurementFailureCauses: [ MeasurementFailedReportCharacteristics: 02000000 MeasurementFailedReportCharacteristics: 04000000 MeasurementFailedReportCharacteristics: 08000000 MeasurementFailedReportCharacteristics: 20000000 MeasurementFailedReportCharacteristics: 40000000 MeasurementFailedReportCharacteristics: 80000000 ] ]",
+ /*
+ SuccessfulOutcome ::= {
+ procedureCode: 9
+ criticality: 0 (reject)
+ value: ResourceStatusResponse ::= {
+ protocolIEs: ProtocolIE-Container ::= {
+ ResourceStatusResponse-IEs ::= {
+ id: 39
+ criticality: 0 (reject)
+ value: 1
+ }
+ ResourceStatusResponse-IEs ::= {
+ id: 40
+ criticality: 0 (reject)
+ value: 75
+ }
+ ResourceStatusResponse-IEs ::= {
+ id: 65
+ criticality: 1 (ignore)
+ value: MeasurementInitiationResult-List ::= {
+ ProtocolIE-Single-Container ::= {
+ id: 66
+ criticality: 1 (ignore)
+ value: MeasurementInitiationResult-Item ::= {
+ cell-ID: ECGI ::= {
+ pLMN-Identity: 13 30 23
+ eUTRANcellIdentifier: 02 B0 30 A0 (4 bits unused)
+ }
+ measurementFailureCause-List: MeasurementFailureCause-List ::= {
+ ProtocolIE-Single-Container ::= {
+ id: 67
+ criticality: 1 (ignore)
+ value: MeasurementFailureCause-Item ::= {
+ measurementFailedReportCharacteristics: 02 00 00 00
+ cause: 20 (measurement-temporarily-not-available)
+ }
+ }
+ ProtocolIE-Single-Container ::= {
+ id: 67
+ criticality: 1 (ignore)
+ value: MeasurementFailureCause-Item ::= {
+ measurementFailedReportCharacteristics: 04 00 00 00
+ cause: 20 (measurement-temporarily-not-available)
+ }
+ }
+ ProtocolIE-Single-Container ::= {
+ id: 67
+ criticality: 1 (ignore)
+ value: MeasurementFailureCause-Item ::= {
+ measurementFailedReportCharacteristics: 08 00 00 00
+ cause: 20 (measurement-temporarily-not-available)
+ }
+ }
+ ProtocolIE-Single-Container ::= {
+ id: 67
+ criticality: 1 (ignore)
+ value: MeasurementFailureCause-Item ::= {
+ measurementFailedReportCharacteristics: 20 00 00 00
+ cause: 20 (measurement-temporarily-not-available)
+ }
+ }
+ ProtocolIE-Single-Container ::= {
+ id: 67
+ criticality: 1 (ignore)
+ value: MeasurementFailureCause-Item ::= {
+ measurementFailedReportCharacteristics: 40 00 00 00
+ cause: 20 (measurement-temporarily-not-available)
+ }
+ }
+ ProtocolIE-Single-Container ::= {
+ id: 67
+ criticality: 1 (ignore)
+ value: MeasurementFailureCause-Item ::= {
+ measurementFailedReportCharacteristics: 80 00 00 00
+ cause: 20 (measurement-temporarily-not-available)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ */
+ packedPdu: "20090065000003002700030000000028000300004a00414050000042404b4013302302b030a2800043400700020000000a000043400700040000000a000043400700080000000a000043400700200000000a000043400700400000000a000043400700800000000a00"},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.packedPdu, func(t *testing.T) {
+ var payload []byte
+
+ _, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
+ if err != nil {
+ t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+ }
+
+ response, err := rsConverters.Convert(payload)
+ if err != nil {
+ t.Errorf("want: success, got: unpack failed. Error: %v\n", err)
+ }
+
+ got := response.String()
+ if len(tc.response) != len(got) {
+ t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", tc.response, response)
+ }
+ if strings.Compare(tc.response, got) != 0 {
+ t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", tc.response, got)
+ }
+ })
+ }
+}
+
+/*unpacking error*/
+
+func TestResourceStatusResponseConverterError(t *testing.T) {
+ logger, _ := logger.InitLogger(logger.InfoLevel)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ rsConverters := NewResourceStatusResponseConverter(unpacker)
+
+ wantError := "unpacking error: #src/asn1codec_utils.c.unpack_pdu_aux - Failed to decode E2AP-PDU (consumed 0), error = 0 Success"
+ //--------------------2006002a
+ inputPayloadAsStr := "2006002b000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"
+ var payload []byte
+ _, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
+ if err != nil {
+ t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+ }
+
+ _, err = rsConverters.Convert(payload)
+ if err != nil {
+ if 0 != strings.Compare(fmt.Sprintf("%s", err), wantError) {
+ t.Errorf("want failure: %s, got: %s", wantError, err)
+ }
+ } else {
+ t.Errorf("want failure: %s, got: success", wantError)
+
+ }
+}
+
+func TestResourceStatusResponseConverterPduOfFailure(t *testing.T) {
+ logger, _ := logger.InitLogger(logger.InfoLevel)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ rsConverters := NewResourceStatusResponseConverter(unpacker)
+
+ wantError := "unexpected PDU, 3"
+ inputPayloadAsStr := "400900170000030027000300000000280003000049000540020a80"
+ var payload []byte
+ _, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
+ if err != nil {
+ t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+ }
+
+ _, err = rsConverters.Convert(payload)
+ if err != nil {
+ if 0 != strings.Compare(fmt.Sprintf("%s", err), wantError) {
+ t.Errorf("want failure: %s, got: %s", wantError, err)
+ }
+ } else {
+ t.Errorf("want failure: %s, got: success", wantError)
+
+ }
+}
+
+func TestResourceStatusResponseConverterWrongPdu(t *testing.T) {
+ logger, _ := logger.InitLogger(logger.InfoLevel)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ rsConverters := NewResourceStatusResponseConverter(unpacker)
+
+ wantError := "unexpected PDU - not a resource status response"
+ inputPayloadAsStr := "2006002a000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"
+ var payload []byte
+ _, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
+ if err != nil {
+ t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+ }
+
+ _, err = rsConverters.Convert(payload)
+ if err != nil {
+ if 0 != strings.Compare(fmt.Sprintf("%s", err), wantError) {
+ t.Errorf("want failure: %s, got: %s", wantError, err)
+ }
+ } else {
+ t.Errorf("want failure: %s, got: success", wantError)
+
+ }
+}
"unsafe"
)
-type Asn1PduUnpacker interface {
- UnpackX2apPduAsString(packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (string, error)
-}
-
type X2apPduUnpacker struct {
- logger *logger.Logger
-
+ logger *logger.Logger
+ maxMessageBufferSize int
}
-func NewX2apPduUnpacker(logger *logger.Logger) Asn1PduUnpacker {
- return &X2apPduUnpacker{logger :logger}
+func NewX2apPduUnpacker(logger *logger.Logger, maxMessageBufferSize int) X2apPduUnpacker {
+ return X2apPduUnpacker{logger: logger, maxMessageBufferSize: maxMessageBufferSize}
}
-func (r X2apPduUnpacker) UnpackX2apPdu(packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (*C.E2AP_PDU_t, error) {
+func (r X2apPduUnpacker) UnpackX2apPdu(packedBuf []byte) (*C.E2AP_PDU_t, error) {
pdu := C.new_pdu()
if pdu == nil {
return nil, errors.New("allocation failure (pdu)")
}
- r.logger.Infof("#x2apPdu_asn1_unpacker.UnpackX2apPdu - Packed pdu(%d):%x", packedBufferSize, packedBuf)
-
- errBuf := make([]C.char, maxMessageBufferSize)
- if !C.per_unpack_pdu(pdu, C.ulong(packedBufferSize), (*C.uchar)(unsafe.Pointer(&packedBuf[0])), C.ulong(len(errBuf)), &errBuf[0]) {
+ 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])))
}
if r.logger.DebugEnabled() {
C.asn1_pdu_printer(pdu, C.size_t(len(errBuf)), &errBuf[0])
- r.logger.Debugf("#x2apPdu_asn1_unpacker.UnpackX2apPdu - PDU: %v packed size:%d", C.GoString(&errBuf[0]), packedBufferSize)
+ r.logger.Debugf("#x2apPdu_asn1_unpacker.UnpackX2apPdu - PDU: %v packed size:%d", C.GoString(&errBuf[0]), len(packedBuf))
}
return pdu, nil
}
-func (r X2apPduUnpacker)UnpackX2apPduAsString(packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (string, error) {
- pdu, err := r.UnpackX2apPdu(packedBufferSize, packedBuf, maxMessageBufferSize)
+func (r X2apPduUnpacker) UnpackX2apPduAsString(packedBuf []byte, maxMessageBufferSize int) (string, error) {
+ pdu, err := r.UnpackX2apPdu(packedBuf)
if err != nil {
return "", err
}
C.asn1_pdu_printer(pdu, C.size_t(len(buf)), &buf[0])
return C.GoString(&buf[0]), nil
}
-
-
-
func TestUnpackX2apPduResponse(t *testing.T) {
logger, _ := logger.InitLogger(logger.DebugLevel)
- unpacker := NewX2apPduUnpacker(logger)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
wantPduAsStr := `UnsuccessfulOutcome ::= {
procedureCode: 9
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
}
- response, err := unpacker.UnpackX2apPduAsString(len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
+ response, err := unpacker.UnpackX2apPduAsString(payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
if err != nil {
t.Errorf("want: success, got: unpack failed. Error: %v\n", err)
}
func TestUnpackX2apPduError(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
- unpacker := NewX2apPduUnpacker(logger)
+ unpacker := NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
wantError := "unpacking error: #src/asn1codec_utils.c.unpack_pdu_aux - Failed to decode E2AP-PDU (consumed 0), error = 0 Success"
//--------------------2006002a
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
}
- _, err = unpacker.UnpackX2apPduAsString(len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
+ _, err = unpacker.UnpackX2apPduAsString(payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
if err != nil {
if 0 != strings.Compare(fmt.Sprintf("%s", err), wantError) {
t.Errorf("want failure: %s, got: %s", wantError, err)
// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
+// #include <stdlib.h>
// #include <asn1codec_utils.h>
// #include <resource_status_request_wrapper.h>
import "C"
type Measurement_ID int64
type ResourceStatusRequestData struct {
- CellID string // PLMNIdentifier:eUTRANCellIdentifier
+ CellIdList []string // PLMNIdentifier:eUTRANCellIdentifier
MeasurementID Measurement_ID
MeasurementID2 Measurement_ID
PartialSuccessAllowed bool
packedBufSize := C.ulong(len(packedBuf))
pduAsString := ""
- var pLMNIdentifier, eUTRANCellIdentifier string
+ pLMNIdentities := make([]*C.uchar, len(request.CellIdList))
+ eUTRANCellIdentifiers := make([]*C.uchar, len(request.CellIdList))
- if _, err := fmt.Sscanf(request.CellID, "%x:%x", &pLMNIdentifier, &eUTRANCellIdentifier); err != nil {
- return nil, "", fmt.Errorf("BuildPackedResourceStatusRequest() - unexpected CellID value [%s] (want: \"<PLMNIdentifier>:<eUTRANCellIdentifier>\"), err: %s", request.CellID, err)
+ for i, cellID := range request.CellIdList {
+ 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.uchar)(C.CBytes(pLMNIdentity)), (*C.uchar)(C.CBytes(eUTRANCellIdentifier))
}
+ defer func() {
+ for _, cPtr := range pLMNIdentities {
+ C.free(unsafe.Pointer(cPtr))
+
+ }
+ for _, cPtr := range eUTRANCellIdentifiers {
+ C.free(unsafe.Pointer(cPtr))
+ }
+
+ }()
+
/*
- 9.2.0 General
- When specifying information elements which are to be represented by bit strings, if not otherwise specifically stated in the semantics description of the concerned IE or elsewhere, the following principle applies with regards to the ordering of bits:
- - The first bit (leftmost bit) contains the most significant bit (MSB);
- - The last bit (rightmost bit) contains the least significant bit (LSB);
- - When importing bit strings from other specifications, the first bit of the bit string contains the first bit of the concerned information.
+ 9.2.0 General
+ When specifying information elements which are to be represented by bit strings, if not otherwise specifically stated in the semantics description of the concerned IE or elsewhere, the following principle applies with regards to the ordering of bits:
+ - The first bit (leftmost bit) contains the most significant bit (MSB);
+ - The last bit (rightmost bit) contains the least significant bit (LSB);
+ - When importing bit strings from other specifications, the first bit of the bit string contains the first bit of the concerned information.
*/
/*reportCharacteristics:
reportCharacteristics := uint32(prbPeriodic<<7 | tnlLoadIndPeriodic<<6 | hwLoadIndPeriodic<<5 | compositeAvailablCapacityPeriodic<<4 | absStatusPeriodic<<3 | rsrpMeasurementPeriodic<<2 | csiPeriodic<<1)
if !C.build_pack_resource_status_request(
- (*C.uchar)(unsafe.Pointer(&[]byte(pLMNIdentifier)[0])),
- (*C.uchar)(unsafe.Pointer(&[]byte(eUTRANCellIdentifier)[0])),
+ (**C.uchar)(unsafe.Pointer(&pLMNIdentities[0])),
+ (**C.uchar)(unsafe.Pointer(&eUTRANCellIdentifiers[0])),
+ C.ulong(len(request.CellIdList)),
C.Measurement_ID_t(request.MeasurementID),
C.Measurement_ID_t(request.MeasurementID2),
C.Registration_Request_t(registrationRequest),
)
/*
- * Create and pack an x2ap setup request.
- * Verify the packed representation matches the want value.
+* Create and pack an x2ap setup request.
+* Verify the packed representation matches the want value.
*/
func TestBuildPackedResourceStatusRequest(t *testing.T) {
var testCases = []struct {
}{
{
request: ResourceStatusRequestData{
- CellID: "0a0b0c:abcd8000",
+ CellIdList: []string{"0a0b0c:abcd8000"},
MeasurementID: 15,
MeasurementID2: 0,
PartialSuccessAllowed: true,
},
{
request: ResourceStatusRequestData{
- CellID: "0a0b0c:abcd8000",
+ CellIdList: []string{"0a0b0c:abcd8000"},
MeasurementID: 15,
MeasurementID2: 0,
PartialSuccessAllowed: true,
},
{
request: ResourceStatusRequestData{
- CellID: "0a0b0c:abcd8000",
+ CellIdList: []string{"0a0b0c:abcd8000"},
MeasurementID: 15,
MeasurementID2: 0,
PartialSuccessAllowed: true,
},
{
request: ResourceStatusRequestData{
- CellID: "0a0b0c:abcd8000",
+ CellIdList: []string{"0a0b0c:abcd8000"},
MeasurementID: 15,
MeasurementID2: 0,
PartialSuccessAllowed: false,
},
packedPdu: "000900370000070027000300000e001c000100002600040e000000001d400d00001f4008000a0b0cabcd8000001e400160006d4001600091400140",
},
+ {
+ request: ResourceStatusRequestData{
+ CellIdList: []string{"0a0b0c:abcd8000", "0b0c0d:acde8000"},
+ MeasurementID: 15,
+ MeasurementID2: 0,
+ PartialSuccessAllowed: true,
+ PrbPeriodic: true,
+ TnlLoadIndPeriodic: true,
+ HwLoadIndPeriodic: true,
+ AbsStatusPeriodic: true,
+ RsrpMeasurementPeriodic: true,
+ CsiPeriodic: true,
+ PeriodicityMS: enums.ReportingPeriodicity_one_thousand_ms,
+ PeriodicityRsrpMeasurementMS: enums.ReportingPeriodicityRSRPMR_one_hundred_20_ms,
+ PeriodicityCsiMS: enums.ReportingPeriodicityCSIR_ms5,
+ },
+ packedPdu: "000900480000080027000300000e001c00010000260004fe000000001d401901001f4008000a0b0cabcd8000001f4008000b0c0dacde8000001e4001000040400100006d4001000091400100",
+ },
}
for _, tc := range testCases {
if err != nil {
t.Errorf("want: success, got: pack failed. Error: %v\n", err)
} else {
- t.Logf("packed resource status request (size=%d): %x\n\n%s", len(payload), payload,asString)
+ t.Logf("packed resource status request (size=%d): %x\n\n%s", len(payload), payload, asString)
tmp := fmt.Sprintf("%x", payload)
if len(tmp) != len(tc.packedPdu) {
t.Errorf("want packed len:%d, got: %d\n", len(tc.packedPdu)/2, len(payload)/2)
func TestBuildPackedResourceStatusRequestError(t *testing.T) {
request := ResourceStatusRequestData{
- CellID: "0a0b0c:abcd8000",
+ CellIdList: []string{"0a0b0c:abcd8000"},
MeasurementID: 15,
MeasurementID2: 0,
PrbPeriodic: true,
PeriodicityRsrpMeasurementMS: enums.ReportingPeriodicityRSRPMR_one_hundred_20_ms,
PeriodicityCsiMS: enums.ReportingPeriodicityCSIR_ms5,
}
- expected:= "packing error: #src/asn1codec_utils.c.pack_pdu_aux - Encoded output of E2AP-PDU, is too big"
+ expected := "packing error: #src/asn1codec_utils.c.pack_pdu_aux - Encoded output of E2AP-PDU, is too big"
_, _, err := BuildPackedResourceStatusRequest(enums.Registration_Request_start, &request, 40 /*max packed buffer*/, MaxAsn1CodecMessageBufferSize /*max message buffer*/, true /*withDebug*/)
if err != nil {
if !strings.Contains(err.Error(), expected) {
func TestBuildPackedResourceStatusInvalidCellID(t *testing.T) {
request := ResourceStatusRequestData{
- CellID: "0a0b0cabcd8000",
+ CellIdList: []string{"0a0b0cabcd8000"},
MeasurementID: 15,
MeasurementID2: 0,
PrbPeriodic: true,
PeriodicityRsrpMeasurementMS: enums.ReportingPeriodicityRSRPMR_one_hundred_20_ms,
PeriodicityCsiMS: enums.ReportingPeriodicityCSIR_ms5,
}
- expected:= "BuildPackedResourceStatusRequest() - unexpected CellID value [0a0b0cabcd8000] (want: \"<PLMNIdentifier>:<eUTRANCellIdentifier>\"), err: unexpected EOF"
+ expected := "BuildPackedResourceStatusRequest() - unexpected CellID value [0a0b0cabcd8000]@0 (want: \"<PLMNIdentifier>:<eUTRANCellIdentifier>\"), err: unexpected EOF"
_, _, err := BuildPackedResourceStatusRequest(enums.Registration_Request_start, &request, MaxAsn1PackedBufferSize /*max packed buffer*/, MaxAsn1CodecMessageBufferSize /*max message buffer*/, true /*withDebug*/)
if err != nil {
if !strings.Contains(err.Error(), expected) {
func TestBuildPackedResourceStatusInvalidPeriodicity(t *testing.T) {
request := ResourceStatusRequestData{
- CellID: "0a0b0c:abcd8000",
+ CellIdList: []string{"0a0b0c:abcd8000"},
MeasurementID: 15,
MeasurementID2: 0,
PrbPeriodic: true,
PeriodicityRsrpMeasurementMS: enums.ReportingPeriodicityRSRPMR_one_hundred_20_ms,
PeriodicityCsiMS: enums.ReportingPeriodicityCSIR_ms5,
}
- expected:= "BuildPackedResourceStatusRequest - packing error: #src/asn1codec_utils.c.pack_pdu_aux - Failed to encode E2AP-PDU, error = 9 Bad file descriptor"
+ expected := "BuildPackedResourceStatusRequest - packing error: #src/asn1codec_utils.c.pack_pdu_aux - Failed to encode E2AP-PDU, error = 9 Bad file descriptor"
+ _, _, err := BuildPackedResourceStatusRequest(enums.Registration_Request_start, &request, MaxAsn1PackedBufferSize /*max packed buffer*/, MaxAsn1CodecMessageBufferSize /*max message buffer*/, true /*withDebug*/)
+ if err != nil {
+ if !strings.Contains(err.Error(), expected) {
+ t.Errorf("want failure:[%s], got: [%s]\n", expected, err)
+ }
+ } else {
+ t.Errorf("want failure: ...%s..., got: success", expected)
+
+ }
+}
+
+func TestBuildPackedResourceStatusTooManyCells(t *testing.T) {
+ request := ResourceStatusRequestData{
+ CellIdList: []string{
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000", "0a0b0c:abcd8000", "0b0c0d:acde8000",
+ "0a0b0c:abcd8000",
+ },
+ MeasurementID: 15,
+ MeasurementID2: 0,
+ PartialSuccessAllowed: true,
+ PrbPeriodic: true,
+ TnlLoadIndPeriodic: true,
+ HwLoadIndPeriodic: true,
+ AbsStatusPeriodic: true,
+ RsrpMeasurementPeriodic: true,
+ CsiPeriodic: true,
+ PeriodicityMS: enums.ReportingPeriodicity_one_thousand_ms,
+ PeriodicityRsrpMeasurementMS: enums.ReportingPeriodicityRSRPMR_one_hundred_20_ms,
+ PeriodicityCsiMS: enums.ReportingPeriodicityCSIR_ms5,
+ }
+
+ expected := "BuildPackedResourceStatusRequest - packing error: #src/asn1codec_utils.c.pack_pdu_aux - Failed to encode E2AP-PDU, error = 9 Bad file descriptor"
_, _, err := BuildPackedResourceStatusRequest(enums.Registration_Request_start, &request, MaxAsn1PackedBufferSize /*max packed buffer*/, MaxAsn1CodecMessageBufferSize /*max message buffer*/, true /*withDebug*/)
if err != nil {
if !strings.Contains(err.Error(), expected) {
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 enums
+
+const Enb1MeasurementId int64 = 1
2: "RIC_TO_RAN",
}
-const (
- UNKNOWN_MESSAGE_DIRECTION MessageDirection = 0
- RAN_TO_RIC MessageDirection = 1
- RIC_TO_RAN MessageDirection = 2
-)
-
func (md MessageDirection) String() string {
s, ok := messageDirectionEnumName[int32(md)]
if ok {
_, ok := messageDirectionEnumName[int32(md)]
if !ok {
- return nil,&json.UnsupportedValueError{}
+ return nil, &json.UnsupportedValueError{}
}
- v:= int32(md)
+ v := int32(md)
return json.Marshal(v)
}
const (
Registration_Request_start Registration_Request = iota
Registration_Request_stop
- Registration_Request_partial_stop
- Registration_Request_add
)
+
+func (rs Registration_Request) String() string {
+ return [...]string{"start", "stop"}[rs]
+}
\ No newline at end of file
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 enums
+
+type RsmAction string
+
+const (
+ Start RsmAction = "start"
+ Stop RsmAction = "stop"
+)
require (
cloud.google.com/go v0.46.3 // indirect
- gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23
- gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23
- gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23
- gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.3.1
+ gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.26
+ gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.26
+ gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.26
+ gerrit.o-ran-sc.org/r/ric-plt/sdlgo v0.5.0
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
github.com/coreos/bbolt v1.3.3 // indirect
github.com/coreos/etcd v3.3.15+incompatible // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
- github.com/go-ozzo/ozzo-validation v3.5.0+incompatible
+ github.com/go-ozzo/ozzo-validation v3.5.0+incompatible // indirect
github.com/gogo/protobuf v1.3.0 // indirect
- github.com/golang/protobuf v1.3.2
github.com/google/go-cmp v0.3.1 // indirect
github.com/google/pprof v0.0.0-20190908185732-236ed259b199 // indirect
github.com/google/uuid v1.1.1 // indirect
gopkg.in/yaml.v2 v2.2.2
)
-replace gerrit.o-ran-sc.org/r/ric-plt/sdlgo => gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.1
+replace gerrit.o-ran-sc.org/r/ric-plt/sdlgo => gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23 h1:JbSOhvj9fVEUF2XZg8cw5QAyeKUi5xXgpwXrrxfDgLM=
gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.23/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.24 h1:tW817tat6fSSK7NuFKEDHSoSsO3z8kr7QORfbn1Hpuc=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.24/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.25/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.26 h1:OQs1i2pNH85IxGiEsN/0yNUzTfiTgGVZwgvmfrkAhds=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.26/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23 h1:akVZc8NWJ9oPujd7cQY3Ti3se4PF1/NoC+Dwt+YzINc=
gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.23/go.mod h1:GXiXLz4ORBeIr0FLIbzENRykgh3Po5uPkX2jICxnRF0=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.24 h1:5ZnhEUygvN5PuTXS2bNt6KavT+Wtuh9Vra+EqZIvw+Q=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.24/go.mod h1:GXiXLz4ORBeIr0FLIbzENRykgh3Po5uPkX2jICxnRF0=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.26 h1:8buj1aJBkoHPFQPfcCJ2MiL9VjdA5iR1kcc1CzNFB00=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.26/go.mod h1:Fh23KkroYw5CRBh39WzZzxpKSkpQWL3scdzGnMngLo8=
gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23 h1:TYV3HE2UNwGOWiA4C226/WhB94crwjuHKIFTgDDvo8I=
gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.23/go.mod h1:uZVjwZjfWV4JJzyQVO/O48Ykph57zfpfMB7nK+WGKX8=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.24 h1:Wwp36IoHwp091lXVCYLtFK6AMhoGAR4NYEgW1C42h6k=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.24/go.mod h1:Qi0e0BsGtsMdyJQS0PBtvHBDKEimjtDjQtVUxGZqTtM=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.26 h1:zGKpxfqz7Ql4rpD53JcWmDTwILrZfe0GIdi/QMslUew=
+gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.26/go.mod h1:DCf5H9yy6kNTXsnUgXAPSuJt22ca4pYm0mo2ovJhLrA=
gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.1 h1:ZIhABs0WLMn8lp1Y3719315/3jbV+yLcovOGScL03eM=
gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.3.1/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
+gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0 h1:+P3XuWKSaMbzh5PNtrW9gkZlCN0hKrZq+Cn8JetwBys=
+gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.0/go.mod h1:y2WhrCvdLkAKdH+ySdHSOSehACJkTMyZghCGVcqoZzc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
)
type RequestHandler interface {
- Handle(request models.Request) (models.IResponse, error)
-}
+ Handle(request models.Request) error
+}
\ No newline at end of file
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 httpmsghandlers
+
+import (
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "rsm/enums"
+ "rsm/logger"
+ "rsm/models"
+ "rsm/rsmerrors"
+ "rsm/services"
+)
+
+type ResourceStatusRequestHandler struct {
+ rNibDataService services.RNibDataService
+ logger *logger.Logger
+ resourceStatusService services.IResourceStatusService
+}
+
+func NewResourceStatusRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService, resourceStatusService services.IResourceStatusService) *ResourceStatusRequestHandler {
+ return &ResourceStatusRequestHandler{
+ resourceStatusService: resourceStatusService,
+ rNibDataService: rNibDataService,
+ logger: logger,
+ }
+}
+
+func (h ResourceStatusRequestHandler) Handle(request models.Request) error {
+
+ resourceStatusRequest := request.(models.ResourceStatusRequest)
+ config, err := h.rNibDataService.GetRsmGeneralConfiguration()
+ if err != nil {
+ return rsmerrors.NewRnibDbError()
+ }
+
+ config.EnableResourceStatus = resourceStatusRequest.EnableResourceStatus
+ err = h.rNibDataService.SaveRsmGeneralConfiguration(config)
+ if err != nil {
+ return rsmerrors.NewRnibDbError()
+ }
+
+ nbIdentityList, err := h.rNibDataService.GetListEnbIds()
+ if err != nil {
+ return rsmerrors.NewRnibDbError()
+ }
+
+ numberOfFails := 0
+ for _, nbIdentity := range nbIdentityList {
+
+ ranName := (*nbIdentity).GetInventoryName()
+
+ nodeb, err := h.rNibDataService.GetNodeb(ranName)
+ if err != nil {
+ h.logger.Errorf("#ResourceStatusRequestHandler.Handle - Couldn't find RAN %s in RSM DB", ranName)
+ numberOfFails++
+ continue
+ }
+
+ h.logger.Infof("#ResourceStatusRequestHandler.Handle - handle RAN: %s started", nodeb.RanName)
+
+ if nodeb.ConnectionStatus != entities.ConnectionStatus_CONNECTED {
+ h.logger.Infof("#ResourceStatusRequestHandler.Handle - RAN name: %s - connection status not CONNECTED, ignore", nodeb.RanName)
+ h.logger.Infof("#ResourceStatusRequestHandler.Handle - handle RAN: %s completed", nodeb.RanName)
+ continue
+ }
+
+ err = h.saveAndSendRsmRanInfo(nodeb, config)
+ if err != nil {
+ numberOfFails++
+ }
+ h.logger.Infof("#ResourceStatusRequestHandler.Handle - handle RAN: %s completed", nodeb.RanName)
+ }
+
+ if numberOfFails > 0 {
+ return rsmerrors.NewRsmError(numberOfFails)
+ }
+ return nil
+}
+
+func (h ResourceStatusRequestHandler) saveAndSendRsmRanInfo(nodebInfo *entities.NodebInfo, config *models.RsmGeneralConfiguration) error {
+
+ rsmRanInfo, err := h.rNibDataService.GetRsmRanInfo(nodebInfo.RanName)
+ if err != nil {
+ return err
+ }
+
+ if config.EnableResourceStatus {
+ return h.handleNotStartedRsmRanInfo(nodebInfo, rsmRanInfo, config)
+ }
+
+ return h.handleNotStoppedRsmRanInfo(nodebInfo, rsmRanInfo, config)
+}
+
+func (h ResourceStatusRequestHandler) handleNotStoppedRsmRanInfo(nodebInfo *entities.NodebInfo, rsmRanInfo *models.RsmRanInfo, config *models.RsmGeneralConfiguration) error {
+ if rsmRanInfo.Action == enums.Stop && rsmRanInfo.ActionStatus {
+ return nil
+ }
+
+ if rsmRanInfo.Enb2MeasurementId == 0 {
+ h.logger.Errorf("#ResourceStatusRequestHandler.handleNotStoppedRsmRanInfo - RAN: %s Enb2MeasurementId is zero", nodebInfo.RanName)
+ return rsmerrors.NewInternalError()
+ }
+
+ if rsmRanInfo.Action != enums.Stop {
+
+ err := h.saveRsmRanInfoStopFalse(rsmRanInfo)
+ if err != nil {
+ return err
+ }
+ }
+
+ return h.resourceStatusService.BuildAndSendStopRequest(nodebInfo, config, rsmRanInfo.Enb1MeasurementId, rsmRanInfo.Enb2MeasurementId)
+}
+
+func (h ResourceStatusRequestHandler) handleNotStartedRsmRanInfo(nodebInfo *entities.NodebInfo, rsmRanInfo *models.RsmRanInfo, config *models.RsmGeneralConfiguration) error {
+ if rsmRanInfo.Action == enums.Start && rsmRanInfo.ActionStatus {
+ return nil
+ }
+
+ if rsmRanInfo.Action != enums.Start {
+
+ err := h.saveRsmRanInfoStartFalse(rsmRanInfo)
+ if err != nil {
+ return err
+ }
+ }
+
+ return h.resourceStatusService.BuildAndSendInitiateRequest(nodebInfo, config, rsmRanInfo.Enb1MeasurementId)
+}
+
+func (h ResourceStatusRequestHandler) saveRsmRanInfoStopFalse(rsmRanInfo *models.RsmRanInfo) error {
+ rsmRanInfo.Action = enums.Stop
+ rsmRanInfo.ActionStatus = false
+
+ return h.rNibDataService.SaveRsmRanInfo(rsmRanInfo)
+}
+
+func (h ResourceStatusRequestHandler) saveRsmRanInfoStartFalse(rsmRanInfo *models.RsmRanInfo) error {
+ rsmRanInfo.Action = enums.Start
+ rsmRanInfo.ActionStatus = false
+ rsmRanInfo.Enb2MeasurementId = 0
+ rsmRanInfo.Enb1MeasurementId = enums.Enb1MeasurementId
+
+ return h.rNibDataService.SaveRsmRanInfo(rsmRanInfo)
+}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 httpmsghandlers_test
+
+import (
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "github.com/pkg/errors"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ "rsm/configuration"
+ "rsm/enums"
+ "rsm/handlers/httpmsghandlers"
+ "rsm/logger"
+ "rsm/mocks"
+ "rsm/models"
+ "rsm/rsmerrors"
+ "rsm/services"
+ "rsm/tests"
+ "testing"
+)
+
+func initTest(t *testing.T) (*httpmsghandlers.ResourceStatusRequestHandler, *mocks.RnibReaderMock, *mocks.RsmReaderMock, *mocks.RsmWriterMock, *mocks.ResourceStatusServiceMock) {
+ log, err := logger.InitLogger(logger.DebugLevel)
+ if err != nil {
+ t.Errorf("#... - failed to initialize logger, error: %s", err)
+ }
+
+ config, err := configuration.ParseConfiguration()
+ if err != nil {
+ t.Errorf("#... - failed to parse configuration error: %s", err)
+ }
+
+ resourceStatusServiceMock := &mocks.ResourceStatusServiceMock{}
+ rnibReaderMock := &mocks.RnibReaderMock{}
+ rsmReaderMock := &mocks.RsmReaderMock{}
+ rsmWriterMock := &mocks.RsmWriterMock{}
+
+ rnibDataService := services.NewRnibDataService(log, config, rnibReaderMock, rsmReaderMock, rsmWriterMock)
+ handler := httpmsghandlers.NewResourceStatusRequestHandler(log, rnibDataService, resourceStatusServiceMock)
+
+ return handler, rnibReaderMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock
+}
+
+func TestResourceStatusRequestHandlerGetConfigError(t *testing.T) {
+
+ handler, _, rsmReaderMock, _, _ := initTest(t)
+
+ err := common.NewInternalError(errors.New("Error"))
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(tests.GetRsmGeneralConfiguration(true), err)
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:true}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ rsmReaderMock.AssertNumberOfCalls(t, "SaveRsmGeneralConfiguration", 0)
+
+ assert.Equal(t, actualErr, rsmerrors.NewRnibDbError())
+}
+
+func TestResourceStatusRequestHandlerSaveConfigError(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, _ := initTest(t)
+
+ err := common.NewInternalError(errors.New("Error"))
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(err)
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:true}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetListEnbIds", 0)
+
+ assert.Equal(t, actualErr, rsmerrors.NewRnibDbError())
+}
+
+func TestResourceStatusRequestHandleGetListEnbIdsError(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, _ := initTest(t)
+
+ err := common.NewInternalError(errors.New("Error"))
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+
+ var nbIdentityList []*entities.NbIdentity
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, err)
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:true}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetNodeb", 0)
+
+ assert.Equal(t, actualErr, rsmerrors.NewRnibDbError())
+}
+
+func TestResourceStatusRequestHandlerTrueStartSuccess(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock := initTest(t)
+
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+
+ nbIdentityList := CreateIdentityList()
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, nil)
+
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
+ readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
+
+ rrInfo1 := &models.RsmRanInfo{RanName:"RanName_1", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:0, Action:enums.Start, ActionStatus:false}
+ rrInfo2 := &models.RsmRanInfo{RanName:"RanName_2", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:0, Action:enums.Start, ActionStatus:true}
+ rrInfo3 := &models.RsmRanInfo{RanName:"RanName_3", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:0, Action:enums.Stop, ActionStatus:false}
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_1").Return(rrInfo1, nil)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_2").Return(rrInfo2, nil)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_3").Return(rrInfo3, nil)
+
+ rsmWriterMock.On("SaveRsmRanInfo", rrInfo3).Return(nil)
+
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", nb1, config, enums.Enb1MeasurementId).Return(nil)
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", nb3, config, enums.Enb1MeasurementId).Return(nil)
+
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:true}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 2)
+
+ assert.Equal(t, actualErr, nil)
+}
+
+func TestResourceStatusRequestHandlerTrueNumberOfFails1(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock := initTest(t)
+
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+
+ nbIdentityList := CreateIdentityList()
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, nil)
+
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
+ nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
+ readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
+
+ err := common.NewInternalError(errors.New("Error"))
+ rrInfo1 := &models.RsmRanInfo{RanName:"RanName_1", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:0, Action:enums.Start, ActionStatus:false}
+ rrInfo3 := &models.RsmRanInfo{RanName:"RanName_3", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:0, Action:enums.Stop, ActionStatus:false}
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_1").Return(rrInfo1, err)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_3").Return(rrInfo3, nil)
+
+ rsmWriterMock.On("SaveRsmRanInfo", rrInfo3).Return(nil)
+
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", nb3, mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
+
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:true}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 1)
+
+ rsmError := rsmerrors.NewRsmError(1)
+ assert.Equal(t, actualErr, rsmError)
+ assert.Equal(t, actualErr.Error(), rsmError.Error())
+}
+
+func TestResourceStatusRequestHandlerTrueNumberOfFails3(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock := initTest(t)
+
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+
+ nbIdentityList := CreateIdentityList()
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, nil)
+
+ err := common.NewInternalError(errors.New("Error"))
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, err)
+ readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
+
+ rrInfo1 := &models.RsmRanInfo{RanName:"RanName_1", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:0, Action:enums.Start, ActionStatus:false}
+ rrInfo3 := &models.RsmRanInfo{RanName:"RanName_3", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:0, Action:enums.Stop, ActionStatus:false}
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_1").Return(rrInfo1, nil)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_3").Return(rrInfo3, nil)
+
+ rsmWriterMock.On("SaveRsmRanInfo", rrInfo3).Return(err)
+
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", nb1, mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(errors.New("Error"))
+
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:true}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 1)
+
+ rsmError := rsmerrors.NewRsmError(3)
+ assert.Equal(t, actualErr, rsmError)
+ assert.Equal(t, actualErr.Error(), rsmError.Error())
+}
+
+func TestResourceStatusRequestHandlerFalseStopSuccess(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock := initTest(t)
+
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+
+ nbIdentityList := CreateIdentityList()
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, nil)
+
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
+ readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
+
+ rrInfo1 := &models.RsmRanInfo{RanName:"RanName_1", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Stop, ActionStatus:false}
+ rrInfo2 := &models.RsmRanInfo{RanName:"RanName_2", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Stop, ActionStatus:true}
+ rrInfo3 := &models.RsmRanInfo{RanName:"RanName_3", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Start, ActionStatus:false}
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_1").Return(rrInfo1, nil)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_2").Return(rrInfo2, nil)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_3").Return(rrInfo3, nil)
+
+ rsmWriterMock.On("SaveRsmRanInfo", rrInfo3).Return(nil)
+
+ resourceStatusServiceMock.On("BuildAndSendStopRequest", nb1, config, rrInfo1.Enb1MeasurementId, rrInfo1.Enb2MeasurementId).Return(nil)
+ resourceStatusServiceMock.On("BuildAndSendStopRequest", nb3, config, rrInfo3.Enb1MeasurementId, rrInfo3.Enb2MeasurementId).Return(nil)
+
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:false}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendStopRequest", 2)
+
+ assert.Equal(t, actualErr, nil)
+}
+
+func TestResourceStatusRequestHandlerFalseNumberOfFails1(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock := initTest(t)
+
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+
+ nbIdentityList := CreateIdentityList()
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, nil)
+
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_DISCONNECTED,}
+ nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
+ readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
+
+ err := common.NewInternalError(errors.New("Error"))
+ rrInfo1 := &models.RsmRanInfo{RanName:"RanName_1", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Stop, ActionStatus:false}
+ rrInfo3 := &models.RsmRanInfo{RanName:"RanName_3", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Start, ActionStatus:false}
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_1").Return(rrInfo1, err)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_3").Return(rrInfo3, nil)
+
+ rsmWriterMock.On("SaveRsmRanInfo", rrInfo3).Return(nil)
+
+ resourceStatusServiceMock.On("BuildAndSendStopRequest", nb3, config, rrInfo3.Enb1MeasurementId, rrInfo3.Enb2MeasurementId).Return(nil)
+
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:false}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendStopRequest", 1)
+
+ rsmError := rsmerrors.NewRsmError(1)
+ assert.Equal(t, actualErr, rsmError)
+ assert.Equal(t, actualErr.Error(), rsmError.Error())
+}
+
+func TestResourceStatusRequestHandlerFalseNumberOfFails3(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock := initTest(t)
+
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+
+ nbIdentityList := CreateIdentityList()
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, nil)
+
+ err := common.NewInternalError(errors.New("Error"))
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, err)
+ readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
+
+ rrInfo1 := &models.RsmRanInfo{RanName:"RanName_1", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Stop, ActionStatus:false}
+ rrInfo3 := &models.RsmRanInfo{RanName:"RanName_3", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Start, ActionStatus:false}
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_1").Return(rrInfo1, nil)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_3").Return(rrInfo3, nil)
+
+ rsmWriterMock.On("SaveRsmRanInfo", rrInfo3).Return(err)
+
+ resourceStatusServiceMock.On("BuildAndSendStopRequest", nb1, config, rrInfo1.Enb1MeasurementId, rrInfo1.Enb2MeasurementId).Return(errors.New("Error"))
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:false}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendStopRequest", 1)
+
+ rsmError := rsmerrors.NewRsmError(3)
+ assert.Equal(t, actualErr, rsmError)
+ assert.Equal(t, actualErr.Error(), rsmError.Error())
+}
+
+func TestResourceStatusRequestHandlerFalseNoEnb2MeasurementId(t *testing.T) {
+
+ handler, readerMock, rsmReaderMock, rsmWriterMock, resourceStatusServiceMock := initTest(t)
+
+ config := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(config, nil)
+ rsmWriterMock.On("SaveRsmGeneralConfiguration", config).Return(nil)
+
+ nbIdentityList := CreateIdentityList()
+ readerMock.On("GetListEnbIds").Return(nbIdentityList, nil)
+
+ nb1 := &entities.NodebInfo{RanName: "RanName_1", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb2 := &entities.NodebInfo{RanName: "RanName_2", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ nb3 := &entities.NodebInfo{RanName: "RanName_3", ConnectionStatus: entities.ConnectionStatus_CONNECTED,}
+ readerMock.On("GetNodeb", "RanName_1").Return(nb1, nil)
+ readerMock.On("GetNodeb", "RanName_2").Return(nb2, nil)
+ readerMock.On("GetNodeb", "RanName_3").Return(nb3, nil)
+
+ rrInfo1 := &models.RsmRanInfo{RanName:"RanName_1", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Stop, ActionStatus:false}
+ rrInfo2 := &models.RsmRanInfo{RanName:"RanName_2", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:2, Action:enums.Stop, ActionStatus:true}
+ rrInfo3 := &models.RsmRanInfo{RanName:"RanName_3", Enb1MeasurementId:enums.Enb1MeasurementId, Enb2MeasurementId:0, Action:enums.Start, ActionStatus:false}
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_1").Return(rrInfo1, nil)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_2").Return(rrInfo2, nil)
+ rsmReaderMock.On("GetRsmRanInfo", "RanName_3").Return(rrInfo3, nil)
+
+ resourceStatusServiceMock.On("BuildAndSendStopRequest", nb1, config, rrInfo1.Enb1MeasurementId, rrInfo1.Enb2MeasurementId).Return(nil)
+
+ resourceStatusRequest := models.ResourceStatusRequest{EnableResourceStatus:false}
+ actualErr := handler.Handle(resourceStatusRequest)
+
+ readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 0)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendStopRequest", 1)
+
+ rsmError := rsmerrors.NewRsmError(1)
+ assert.Equal(t, actualErr, rsmError)
+ assert.Equal(t, actualErr.Error(), rsmError.Error())
+}
+
+func CreateIdentityList() []*entities.NbIdentity {
+ nbIdentity1 := entities.NbIdentity{InventoryName: "RanName_1"}
+ nbIdentity2 := entities.NbIdentity{InventoryName: "RanName_2"}
+ nbIdentity3 := entities.NbIdentity{InventoryName: "RanName_3"}
+
+ var nbIdentityList []*entities.NbIdentity
+ nbIdentityList = append(nbIdentityList, &nbIdentity1)
+ nbIdentityList = append(nbIdentityList, &nbIdentity2)
+ nbIdentityList = append(nbIdentityList, &nbIdentity3)
+
+ return nbIdentityList
+}
\ No newline at end of file
)
type ResourceStatusFailureHandler struct {
- logger *logger.Logger
- unpacker converters.Asn1PduUnpacker
+ logger *logger.Logger
+ converter converters.IResourceStatusResponseConverter
}
-func NewResourceStatusFailureHandler(logger *logger.Logger, unpacker converters.Asn1PduUnpacker) ResourceStatusFailureHandler {
+func NewResourceStatusFailureHandler(logger *logger.Logger, converter converters.IResourceStatusResponseConverter) ResourceStatusFailureHandler {
return ResourceStatusFailureHandler{
- logger:logger,
- unpacker: unpacker,
+ logger: logger,
+ converter: converter,
}
}
func (h ResourceStatusFailureHandler) Handle(request *models.RmrRequest) {
h.logger.Infof("#ResourceStatusFailureHandler.Handle - RAN name: %s - Received resource status failure notification", request.RanName)
- pduAsString, err := h.unpacker.UnpackX2apPduAsString(request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
- if err != nil {
- h.logger.Errorf("#ResourceStatusFailureHandler.Handle - unpack failed. Error: %v", err)
- } else {
- h.logger.Infof("#ResourceStatusFailureHandler.Handle - RAN name: %s - message: %s", request.RanName, pduAsString)
+ if h.logger.DebugEnabled() {
+ pduAsString, err := h.converter.UnpackX2apPduAsString(request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+ if err != nil {
+ h.logger.Errorf("#ResourceStatusFailureHandler.Handle - RAN name: %s - unpack failed. Error: %v", request.RanName, err)
+ return
+ }
+ h.logger.Debugf("#ResourceStatusFailureHandler.Handle - RAN name: %s - message: %s", request.RanName, pduAsString)
}
+ //response, err := h.converter.Convert(request.Payload)
+ //if err != nil {
+ // h.logger.Errorf("#ResourceStatusFailureHandler.Handle - RAN name: %s - unpack failed. Error: %v", request.RanName, err)
+ // return
+ //}
+ //
+ ///*The RSM creates one measurement per cell*/
+ //
+ //if response.MeasurementInitiationResults == nil {
+ // h.logger.Infof("#ResourceStatusFailureHandler.Handle - RAN name: %s - ENB1_Measurement_ID: %d, ENB2_Measurement_ID: %d",
+ // request.RanName,
+ // response.ENB1_Measurement_ID,
+ // response.ENB2_Measurement_ID)
+ //} else {
+ // h.logger.Infof("#ResourceStatusFailureHandler.Handle - RAN name: %s - ENB1_Measurement_ID: %d, ENB2_Measurement_ID: %d, CellId: %s, FailedReportCharacteristics: %x",
+ // request.RanName,
+ // response.ENB1_Measurement_ID,
+ // response.ENB2_Measurement_ID,
+ // response.MeasurementInitiationResults[0].CellId,
+ // response.MeasurementInitiationResults[0].MeasurementFailureCauses[0].MeasurementFailedReportCharacteristics)
+ //}
}
-
-
package rmrmsghandlers
-import (
- "fmt"
- "rsm/e2pdus"
- "rsm/logger"
- "rsm/mocks"
- "rsm/models"
- "testing"
- "time"
-)
-
-// Verify UnpackX2apPduAsString is called
-func TestFailureHandler(t *testing.T) {
- logger, err := logger.InitLogger(logger.DebugLevel)
+// Verify UnpackX2apPduAsString() and Convert() are called
+/*
+func TestResourceStatusFailureHandlerConvertFailure(t *testing.T) {
+ logger, err := logger.InitLogger(logger.InfoLevel)
if err != nil {
t.Errorf("#... - failed to initialize logger, error: %s", err)
}
- payload:= []byte("aaa")
- req:= models.RmrRequest{RanName: "test", StartTime:time.Now(), Payload:payload,Len:len(payload)}
- unpackerMock:=mocks.Asn1PduUnpackerMock{}
- unpackerMock.On("UnpackX2apPduAsString", req.Len, req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(string(payload), nil)
- h:= NewResourceStatusFailureHandler(logger, &unpackerMock)
+ payload := []byte("aaa")
+ req := models.RmrRequest{RanName: "test", StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ converterMock := mocks.ResourceStatusFailureConverterMock{}
+ //converterMock.On("UnpackX2apPduAsString", req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(string(payload), nil)
+ converterMock.On("Convert", req.Payload).Return((*models.ResourceStatusResponse)(nil), fmt.Errorf("error"))
+ h := NewResourceStatusFailureHandler(logger, &converterMock)
h.Handle(&req)
- unpackerMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ //converterMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ converterMock.AssertNumberOfCalls(t, "Convert", 1)
}
-func TestFailureHandlerError(t *testing.T) {
+func TestResourceStatusFailureHandlerUnpackFailure(t *testing.T) {
logger, err := logger.InitLogger(logger.DebugLevel)
if err != nil {
t.Errorf("#... - failed to initialize logger, error: %s", err)
}
- payload:= []byte("aaa")
- req:= models.RmrRequest{RanName: "test", StartTime:time.Now(), Payload:payload,Len:len(payload)}
- unpackerMock:=mocks.Asn1PduUnpackerMock{}
+ payload := []byte("aaa")
+ req := models.RmrRequest{RanName: "test", StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ converterMock := mocks.ResourceStatusFailureConverterMock{}
err = fmt.Errorf("error")
var payloadAsString string
- unpackerMock.On("UnpackX2apPduAsString", req.Len, req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(payloadAsString, err)
- h:= NewResourceStatusFailureHandler(logger, &unpackerMock)
+ converterMock.On("UnpackX2apPduAsString", req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(payloadAsString, err)
+ converterMock.On("Convert", req.Payload).Return((*models.ResourceStatusResponse)(nil), fmt.Errorf("error"))
+ h := NewResourceStatusFailureHandler(logger, &converterMock)
+
+ h.Handle(&req)
+
+ converterMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ converterMock.AssertNumberOfCalls(t, "Convert", 0)
+}
+*/
+
+/*
+func TestResourceStatusFailureHandler(t *testing.T) {
+ logger, err := logger.InitLogger(logger.InfoLevel)
+ if err != nil {
+ t.Errorf("#... - failed to initialize logger, error: %s", err)
+ }
+ unpacker := converters.NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ converter := converters.NewResourceStatusFailureConverter(unpacker)
+ var payload []byte
+ fmt.Sscanf("400900320000040027000300000e0028000300000c00054001620044401800004540130002f8290007ab500000434006000000000740", "%x", &payload)
+ req := models.RmrRequest{RanName: "test", StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ h := NewResourceStatusFailureHandler(logger, converter)
h.Handle(&req)
+}
+
+func TestResourceStatusFailureHandlerMinimalPdu(t *testing.T) {
+ logger, err := logger.InitLogger(logger.InfoLevel)
+ if err != nil {
+ t.Errorf("#... - failed to initialize logger, error: %s", err)
+ }
+ unpacker := converters.NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ converter := converters.NewResourceStatusFailureConverter(unpacker)
+ var payload []byte
+ fmt.Sscanf("400900170000030027000300000000280003000049000540020a80", "%x", &payload)
+ req := models.RmrRequest{RanName: "test", StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ h := NewResourceStatusFailureHandler(logger, converter)
- unpackerMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ h.Handle(&req)
}
+*/
\ No newline at end of file
import (
"encoding/json"
+ "fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
- "rsm/configuration"
- "rsm/e2pdus"
+ "rsm/enums"
"rsm/logger"
- "rsm/managers"
"rsm/models"
+ "rsm/services"
)
type ResourceStatusInitiateNotificationHandler struct {
- logger *logger.Logger
- config *configuration.Configuration
- resourceStatusInitiateManager managers.IResourceStatusInitiateManager
- requestName string
+ logger *logger.Logger
+ rnibDataService services.RNibDataService
+ resourceStatusService services.IResourceStatusService
+ requestName string
}
-func NewResourceStatusInitiateNotificationHandler(logger *logger.Logger, config *configuration.Configuration, resourceStatusInitiateManager managers.IResourceStatusInitiateManager, requestName string) ResourceStatusInitiateNotificationHandler {
+func NewResourceStatusInitiateNotificationHandler(logger *logger.Logger, rnibDataService services.RNibDataService, resourceStatusService services.IResourceStatusService, requestName string) ResourceStatusInitiateNotificationHandler {
return ResourceStatusInitiateNotificationHandler{
- logger: logger,
- config: config,
- resourceStatusInitiateManager: resourceStatusInitiateManager,
- requestName: requestName,
+ logger: logger,
+ rnibDataService: rnibDataService,
+ resourceStatusService: resourceStatusService,
+ requestName: requestName,
}
}
+func (h ResourceStatusInitiateNotificationHandler) UnmarshalResourceStatusPayload(inventoryName string, payload []byte) (*models.ResourceStatusPayload, error) {
+ unmarshalledPayload := models.ResourceStatusPayload{}
+ err := json.Unmarshal(payload, &unmarshalledPayload)
+
+ if err != nil {
+ h.logger.Errorf("#ResourceStatusInitiateNotificationHandler.UnmarshalResourceStatusPayload - RAN name: %s - Error unmarshaling RMR request payload: %v", inventoryName, err)
+ return nil, err
+ }
+
+ if unmarshalledPayload.NodeType == entities.Node_UNKNOWN {
+ h.logger.Errorf("#ResourceStatusInitiateNotificationHandler.UnmarshalResourceStatusPayload - RAN name: %s - Unknown Node Type", inventoryName)
+ return nil, fmt.Errorf("unknown node type for RAN %s", inventoryName)
+ }
+
+ h.logger.Infof("#ResourceStatusInitiateNotificationHandler.UnmarshalResourceStatusPayload - Unmarshaled payload successfully: %+v", unmarshalledPayload)
+ return &unmarshalledPayload, nil
+
+}
+
+func (h ResourceStatusInitiateNotificationHandler) SaveRsmRanInfoStopTrue(inventoryName string) {
+ rsmRanInfo := models.NewRsmRanInfo(inventoryName, 0, 0, enums.Stop, true)
+ _ = h.rnibDataService.SaveRsmRanInfo(rsmRanInfo)
+}
+
func (h ResourceStatusInitiateNotificationHandler) Handle(request *models.RmrRequest) {
inventoryName := request.RanName
- h.logger.Infof("#ResourceStatusInitiateNotificationHandler - RAN name: %s - Received %s notification", inventoryName, h.requestName)
+ h.logger.Infof("#ResourceStatusInitiateNotificationHandler.Handle - RAN name: %s - Received %s notification", inventoryName, h.requestName)
+
+ payload, err := h.UnmarshalResourceStatusPayload(inventoryName, request.Payload)
- if !isResourceStatusEnabled(h.config) {
- h.logger.Warnf("#ResourceStatusInitiateNotificationHandler - RAN name: %s - resource status is disabled", inventoryName)
+ if err != nil {
return
}
- payload := models.ResourceStatusPayload{}
- err := json.Unmarshal(request.Payload, &payload)
+ if payload.NodeType != entities.Node_ENB {
+ h.logger.Debugf("#ResourceStatusInitiateNotificationHandler.Handle - RAN name: %s, Node type isn't ENB", inventoryName)
+ return
+ }
+
+ config, err := h.rnibDataService.GetRsmGeneralConfiguration()
if err != nil {
- h.logger.Errorf("#ResourceStatusInitiateNotificationHandler - RAN name: %s - Error unmarshaling RMR request payload: %v", inventoryName, err)
return
}
- h.logger.Infof("#ResourceStatusInitiateNotificationHandler - Unmarshaled payload successfully: %+v", payload)
+ if !config.EnableResourceStatus {
+ h.SaveRsmRanInfoStopTrue(inventoryName)
+ return
+ }
- if payload.NodeType != entities.Node_ENB {
- h.logger.Debugf("#ResourceStatusInitiateNotificationHandler - RAN name: %s, Node type isn't ENB", inventoryName)
+ nodeb, err := h.rnibDataService.GetNodeb(inventoryName)
+
+ if err != nil {
return
}
- resourceStatusInitiateRequestParams := &e2pdus.ResourceStatusRequestData{}
- populateResourceStatusInitiateRequestParams(resourceStatusInitiateRequestParams, h.config)
+ nodebConnectionStatus := nodeb.GetConnectionStatus()
- _ = h.resourceStatusInitiateManager.Execute(inventoryName, resourceStatusInitiateRequestParams)
-}
+ h.logger.Infof("#ResourceStatusInitiateNotificationHandler.Handle - RAN name: %s - successfully fetched RAN from db. RAN's connection status: %s", inventoryName, nodebConnectionStatus)
-func isResourceStatusEnabled(configuration *configuration.Configuration) bool {
- return configuration.ResourceStatusParams.EnableResourceStatus
-}
+ if nodebConnectionStatus != entities.ConnectionStatus_CONNECTED {
+ h.logger.Errorf("#ResourceStatusInitiateNotificationHandler.Handle - RAN name: %s - RAN's connection status isn't CONNECTED", inventoryName)
+ h.SaveRsmRanInfoStopTrue(inventoryName)
+ return
+ }
+
+ rsmRanInfo := models.NewRsmRanInfo(inventoryName, enums.Enb1MeasurementId, 0, enums.Start, false)
+ err = h.rnibDataService.SaveRsmRanInfo(rsmRanInfo)
-func populateResourceStatusInitiateRequestParams(params *e2pdus.ResourceStatusRequestData, config *configuration.Configuration) {
- params.PartialSuccessAllowed = config.ResourceStatusParams.PartialSuccessAllowed
- params.PrbPeriodic = config.ResourceStatusParams.PrbPeriodic
- params.TnlLoadIndPeriodic = config.ResourceStatusParams.TnlLoadIndPeriodic
- params.HwLoadIndPeriodic = config.ResourceStatusParams.HwLoadIndPeriodic
- params.AbsStatusPeriodic = config.ResourceStatusParams.AbsStatusPeriodic
- params.RsrpMeasurementPeriodic = config.ResourceStatusParams.RsrpMeasurementPeriodic
- params.CsiPeriodic = config.ResourceStatusParams.CsiPeriodic
- params.PeriodicityMS = config.ResourceStatusParams.PeriodicityMs
- params.PeriodicityRsrpMeasurementMS = config.ResourceStatusParams.PeriodicityRsrpMeasurementMs
- params.PeriodicityCsiMS = config.ResourceStatusParams.PeriodicityCsiMs
+ if err != nil {
+ return
+ }
+
+ err = h.resourceStatusService.BuildAndSendInitiateRequest(nodeb, config, rsmRanInfo.Enb1MeasurementId)
+
+ if err != nil {
+ h.SaveRsmRanInfoStopTrue(inventoryName)
+ return
+ }
}
package rmrmsghandlers
import (
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"rsm/configuration"
- "rsm/e2pdus"
+ "rsm/enums"
"rsm/logger"
"rsm/mocks"
"rsm/models"
+ "rsm/services"
+ "rsm/tests"
"testing"
"time"
)
-func initRanConnectedNotificationHandlerTest(t *testing.T, requestName string) (ResourceStatusInitiateNotificationHandler, *mocks.ResourceStatusInitiateManagerMock, *configuration.Configuration) {
+const RanName = "test"
+
+
+func initRanConnectedNotificationHandlerTest(t *testing.T, requestName string) (ResourceStatusInitiateNotificationHandler, *mocks.RnibReaderMock, *mocks.ResourceStatusServiceMock, *mocks.RsmWriterMock, *mocks.RsmReaderMock) {
log, err := logger.InitLogger(logger.DebugLevel)
if err != nil {
t.Errorf("#... - failed to initialize logger, error: %s", err)
}
+
config, err := configuration.ParseConfiguration()
if err != nil {
t.Errorf("#... - failed to parse configuration error: %s", err)
}
- managerMock := &mocks.ResourceStatusInitiateManagerMock{}
- h := NewResourceStatusInitiateNotificationHandler(log, config, managerMock, requestName)
- return h, managerMock, config
+
+ resourceStatusServiceMock := &mocks.ResourceStatusServiceMock{}
+ rnibReaderMock := &mocks.RnibReaderMock{}
+ rsmReaderMock := &mocks.RsmReaderMock{}
+ rsmWriterMock := &mocks.RsmWriterMock{}
+
+ rnibDataService := services.NewRnibDataService(log, config, rnibReaderMock, rsmReaderMock, rsmWriterMock)
+
+ h := NewResourceStatusInitiateNotificationHandler(log, rnibDataService, resourceStatusServiceMock, requestName)
+ return h, rnibReaderMock, resourceStatusServiceMock, rsmWriterMock, rsmReaderMock
}
func TestHandlerInit(t *testing.T) {
- h, _, _ := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+ h, _, _, _, _ := initRanConnectedNotificationHandlerTest(t, "RanConnected")
assert.NotNil(t, h)
}
-func TestHandleSuccess(t *testing.T) {
- h, managerMock, config := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+func TestJsonUnmarshalError(t *testing.T) {
+ h, rnibReaderMock, resourceStatusServiceMock, _, _ := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+
+ payloadStr := "blabla"
+ payload := []byte(payloadStr)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+
+ rnibReaderMock.On("GetNodeb", RanName).Return(mock.AnythingOfType("*entities.NodebInfo"))
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
+ h.Handle(rmrReq)
+ rnibReaderMock.AssertNumberOfCalls(t, "GetNodeb", 0)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
+}
+
+func TestUnknownJsonValue(t *testing.T) {
+ h, rnibReaderMock, resourceStatusServiceMock, _, _ := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+
+ payloadStr := "{\"whatever\":3}"
+ payload := []byte(payloadStr)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+
+ rnibReaderMock.On("GetNodeb", RanName).Return(mock.AnythingOfType("*entities.NodebInfo"))
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
+ h.Handle(rmrReq)
+ rnibReaderMock.AssertNumberOfCalls(t, "GetNodeb", 0)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
+}
+
+func TestHandleGnbNode(t *testing.T) {
+ h, rnibReaderMock, resourceStatusServiceMock, _, _ := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+ payloadStr := "{\"nodeType\":2, \"messageDirection\":1}"
+ payload := []byte(payloadStr)
+ rmrReq := &models.RmrRequest{RanName: "RAN1", Payload: payload, Len: len(payload), StartTime: time.Now()}
+ rnibReaderMock.On("GetNodeb", RanName).Return(mock.AnythingOfType("*entities.NodebInfo"))
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
+ h.Handle(rmrReq)
+ rnibReaderMock.AssertNumberOfCalls(t, "GetNodeb", 0)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
+}
+
+func TestGetRsmGeneralConfigurationFailure(t *testing.T) {
+ h, _, resourceStatusServiceMock, _, rsmReaderMock := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+ var rgc models.RsmGeneralConfiguration
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(&rgc, common.NewInternalError(errors.New("Error")))
payloadStr := "{\"nodeType\":1, \"messageDirection\":1}"
payload := []byte(payloadStr)
- rmrReq := &models.RmrRequest{RanName:"RAN1", Payload:payload, Len:len(payload), StartTime:time.Now()}
- managerMock.On("Execute", rmrReq.RanName, mock.AnythingOfType("*e2pdus.ResourceStatusRequestData")).Return(nil)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
+ h.Handle(rmrReq)
+ rsmReaderMock.AssertCalled(t, "GetRsmGeneralConfiguration")
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
+}
- resourceStatusInitiateRequestParams := &e2pdus.ResourceStatusRequestData{}
- populateResourceStatusInitiateRequestParams(resourceStatusInitiateRequestParams, config)
+func TestEnableResourceStatusFalse(t *testing.T) {
+ h, _, resourceStatusServiceMock, rsmWriterMock, rsmReaderMock := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+ var err error
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(tests.GetRsmGeneralConfiguration(false), err)
+ rsmRanInfo := models.RsmRanInfo{RanName, 0, 0, enums.Stop, true}
+ rsmWriterMock.On("SaveRsmRanInfo", &rsmRanInfo).Return(err)
+ payloadStr := "{\"nodeType\":1, \"messageDirection\":1}"
+ payload := []byte(payloadStr)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
h.Handle(rmrReq)
- managerMock.AssertCalled(t, "Execute", rmrReq.RanName, resourceStatusInitiateRequestParams)
+ rsmReaderMock.AssertCalled(t, "GetRsmGeneralConfiguration")
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
}
-func TestHandleResourceStatusNotEnabled(t *testing.T) {
- h, managerMock, config := initRanConnectedNotificationHandlerTest(t, "RanConnected")
- config.ResourceStatusParams.EnableResourceStatus = false
+func TestEnableResourceStatusFalseSaveRsmRanInfoFailure(t *testing.T) {
+ h, _, resourceStatusServiceMock, rsmWriterMock, rsmReaderMock := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+ var err error
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(tests.GetRsmGeneralConfiguration(false), err)
+ rsmRanInfo := models.RsmRanInfo{RanName, 0, 0, enums.Stop, true}
+ rsmWriterMock.On("SaveRsmRanInfo", &rsmRanInfo).Return(common.NewInternalError(errors.New("Error")))
payloadStr := "{\"nodeType\":1, \"messageDirection\":1}"
payload := []byte(payloadStr)
- rmrReq := &models.RmrRequest{RanName:"RAN1", Payload:payload, Len:len(payload), StartTime:time.Now()}
- managerMock.On("Execute", rmrReq.RanName, mock.AnythingOfType("*e2pdus.ResourceStatusRequestData")).Return(nil)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
+ h.Handle(rmrReq)
+ rsmReaderMock.AssertCalled(t, "GetRsmGeneralConfiguration")
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
+}
+func TestGetNodebFailure(t *testing.T) {
+ h, rnibReaderMock, resourceStatusServiceMock, _, rsmReaderMock := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+
+ payloadStr := "{\"nodeType\":1, \"messageDirection\":1}"
+ payload := []byte(payloadStr)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+
+ var err error
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(tests.GetRsmGeneralConfiguration(true), err)
+
+ var nodebInfo *entities.NodebInfo
+ rnibReaderMock.On("GetNodeb", RanName).Return(nodebInfo, common.NewInternalError(errors.New("Error")))
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
h.Handle(rmrReq)
- managerMock.AssertNumberOfCalls(t, "Execute", 0)
+ rsmReaderMock.AssertCalled(t, "GetRsmGeneralConfiguration")
+ rnibReaderMock.AssertCalled(t, "GetNodeb", RanName)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
}
-func TestHandleUnknownJson(t *testing.T) {
- h, managerMock, _ := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+func TestInvalidConnectionStatus(t *testing.T) {
+ h, rnibReaderMock, resourceStatusServiceMock, rsmWriterMock, rsmReaderMock := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+ var err error
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(tests.GetRsmGeneralConfiguration(true), err)
+ rnibReaderMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}, err)
+ rsmRanInfo := models.RsmRanInfo{RanName, 0, 0, enums.Stop, true}
+ rsmWriterMock.On("SaveRsmRanInfo", &rsmRanInfo).Return(err)
- payloadStr := "blablabla"
+ payloadStr := "{\"nodeType\":1, \"messageDirection\":1}"
payload := []byte(payloadStr)
- rmrReq := &models.RmrRequest{RanName:"RAN1", Payload:payload, Len:len(payload), StartTime:time.Now()}
- managerMock.On("Execute", rmrReq.RanName, mock.AnythingOfType("*e2pdus.ResourceStatusRequestData")).Return(nil)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
+ h.Handle(rmrReq)
+ rsmReaderMock.AssertCalled(t, "GetRsmGeneralConfiguration")
+ rnibReaderMock.AssertCalled(t, "GetNodeb", RanName)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
+}
+
+func TestEnableResourceStatusTrueSaveRsmRanInfoFailure(t *testing.T) {
+ h, rnibReaderMock, resourceStatusServiceMock, rsmWriterMock, rsmReaderMock := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+ payloadStr := "{\"nodeType\":1, \"messageDirection\":1}"
+ payload := []byte(payloadStr)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+
+ var err error
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(tests.GetRsmGeneralConfiguration(true), err)
+ rnibReaderMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}, err)
+ rsmRanInfo := models.RsmRanInfo{RanName, enums.Enb1MeasurementId, 0, enums.Start, false}
+ rsmWriterMock.On("SaveRsmRanInfo", &rsmRanInfo).Return(common.NewInternalError(errors.New("Error")))
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", mock.AnythingOfType("*entities.NodebInfo"), mock.AnythingOfType("*models.RsmGeneralConfiguration"), enums.Enb1MeasurementId).Return(nil)
h.Handle(rmrReq)
- managerMock.AssertNumberOfCalls(t, "Execute", 0)
+ rsmReaderMock.AssertCalled(t, "GetRsmGeneralConfiguration")
+ rnibReaderMock.AssertCalled(t, "GetNodeb", RanName)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 0)
}
-func TestHandleGnbNode(t *testing.T) {
- h, managerMock, _ := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+func TestBuildAndSendSuccess(t *testing.T) {
+ h, rnibReaderMock, resourceStatusServiceMock, rsmWriterMock, rsmReaderMock := initRanConnectedNotificationHandlerTest(t, "RanConnected")
- payloadStr := "{\"nodeType\":2, \"messageDirection\":1}"
+ payloadStr := "{\"nodeType\":1, \"messageDirection\":1}"
payload := []byte(payloadStr)
- rmrReq := &models.RmrRequest{RanName:"RAN1", Payload:payload, Len:len(payload), StartTime:time.Now()}
- managerMock.On("Execute", rmrReq.RanName, mock.AnythingOfType("*e2pdus.ResourceStatusRequestData")).Return(nil)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+ var err error
+ rgc := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(rgc, err)
+ nodebInfo := &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+ rnibReaderMock.On("GetNodeb", RanName).Return(nodebInfo, err)
+ rsmRanInfo := models.RsmRanInfo{RanName, enums.Enb1MeasurementId, 0, enums.Start, false}
+ rsmWriterMock.On("SaveRsmRanInfo", &rsmRanInfo).Return(err)
+
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", nodebInfo, rgc, enums.Enb1MeasurementId).Return(nil)
+ h.Handle(rmrReq)
+ rnibReaderMock.AssertCalled(t, "GetNodeb", RanName)
+ rsmReaderMock.AssertCalled(t, "GetRsmGeneralConfiguration")
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 1)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 1)
+}
+
+func TestBuildAndSendError(t *testing.T) {
+ h, rnibReaderMock, resourceStatusServiceMock, rsmWriterMock, rsmReaderMock := initRanConnectedNotificationHandlerTest(t, "RanConnected")
+ var err error
+ nodebInfo := &entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_CONNECTED}
+ rgc := tests.GetRsmGeneralConfiguration(true)
+ rsmReaderMock.On("GetRsmGeneralConfiguration").Return(rgc, err)
+ rnibReaderMock.On("GetNodeb", RanName).Return(nodebInfo, err)
+ rsmRanInfoStart := models.RsmRanInfo{RanName, enums.Enb1MeasurementId, 0, enums.Start, false}
+ rsmWriterMock.On("SaveRsmRanInfo", &rsmRanInfoStart).Return(err)
+ rsmRanInfoStop := models.RsmRanInfo{RanName, 0, 0, enums.Stop, true}
+ rsmWriterMock.On("SaveRsmRanInfo", &rsmRanInfoStop).Return(err)
+ payloadStr := "{\"nodeType\":1, \"messageDirection\":1}"
+ payload := []byte(payloadStr)
+ rmrReq := &models.RmrRequest{RanName: RanName, Payload: payload, Len: len(payload), StartTime: time.Now()}
+ resourceStatusServiceMock.On("BuildAndSendInitiateRequest", nodebInfo, rgc, enums.Enb1MeasurementId).Return(common.NewInternalError(errors.New("Error")))
h.Handle(rmrReq)
- managerMock.AssertNumberOfCalls(t, "Execute", 0)
+ rsmReaderMock.AssertCalled(t, "GetRsmGeneralConfiguration")
+ rnibReaderMock.AssertCalled(t, "GetNodeb", RanName)
+ resourceStatusServiceMock.AssertNumberOfCalls(t, "BuildAndSendInitiateRequest", 1)
+ rsmWriterMock.AssertNumberOfCalls(t, "SaveRsmRanInfo", 2)
}
package rmrmsghandlers
-
import (
-// "rsm/converters"
-// "rsm/e2pdus"
+ "rsm/converters"
+ "rsm/e2pdus"
"rsm/logger"
"rsm/models"
+ "rsm/services"
)
type ResourceStatusResponseHandler struct {
- logger *logger.Logger
+ logger *logger.Logger
+ rnibDataService services.RNibDataService
+ converter converters.IResourceStatusResponseConverter
}
-func NewResourceStatusResponseHandler(logger *logger.Logger) ResourceStatusResponseHandler {
+func NewResourceStatusResponseHandler(logger *logger.Logger, converter converters.IResourceStatusResponseConverter, rnibDataService services.RNibDataService) ResourceStatusResponseHandler {
return ResourceStatusResponseHandler{
- logger:logger,
+ logger: logger,
+ converter: converter,
+ rnibDataService: rnibDataService,
}
}
func (h ResourceStatusResponseHandler) Handle(request *models.RmrRequest) {
h.logger.Infof("#ResourceStatusResponseHandler.Handle - RAN name: %s - Received resource status response notification", request.RanName)
- //_, err := converters.UnpackX2apPduAsString(h.logger, request.Len, request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
- //if err != nil {
- // logger.Errorf("#ResourceStatusResponseHandler.Handle - unpack failed. Error: %v", err)
- //}
+
+ if h.logger.DebugEnabled() {
+ pduAsString, err := h.converter.UnpackX2apPduAsString(request.Payload, e2pdus.MaxAsn1CodecMessageBufferSize)
+ if err != nil {
+ h.logger.Errorf("#ResourceStatusResponseHandler.Handle - RAN name: %s - unpack failed. Error: %v", request.RanName, err)
+ return
+ }
+ h.logger.Debugf("#ResourceStatusResponseHandler.Handle - RAN name: %s - pdu: %s", request.RanName, pduAsString)
+ }
+
+ response, err := h.converter.Convert(request.Payload)
+
+ if err != nil {
+ h.logger.Errorf("#ResourceStatusResponseHandler.Handle - RAN name: %s - unpack failed. Error: %v", request.RanName, err)
+ return
+ }
+
+ if response.ENB2_Measurement_ID == 0 {
+ h.logger.Errorf("#ResourceStatusResponseHandler.Handle - RAN name: %s - ignoring response without ENB2_Measurement_ID", request.RanName)
+ return
+ }
+
+ h.logger.Infof("#ResourceStatusResponseHandler.Handle - RAN name: %s - (success) ENB1_Measurement_ID: %d, ENB2_Measurement_ID: %d",
+ request.RanName,
+ response.ENB1_Measurement_ID,
+ response.ENB2_Measurement_ID)
+
+ rsmRanInfo, err := h.rnibDataService.GetRsmRanInfo(request.RanName)
+
+ if err != nil {
+ return
+ }
+
+ rsmRanInfo.Enb2MeasurementId = response.ENB2_Measurement_ID
+ rsmRanInfo.ActionStatus = true
+
+ err = h.rnibDataService.SaveRsmRanInfo(rsmRanInfo)
+
+ if err != nil {
+ return
+ }
+
+ h.logger.Infof("#ResourceStatusResponseHandler.Handle - RAN name: %s - Successfully updated RsmRanInfo", request.RanName)
}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 rmrmsghandlers
+
+import (
+ "fmt"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+ "github.com/pkg/errors"
+ "rsm/configuration"
+ "rsm/e2pdus"
+ "rsm/enums"
+ "rsm/logger"
+ "rsm/mocks"
+ "rsm/models"
+ "rsm/services"
+ "testing"
+ "time"
+)
+
+func initResourceStatusResponseHandlerTest(t *testing.T) (*mocks.ResourceStatusResponseConverterMock, ResourceStatusResponseHandler, *mocks.RsmReaderMock, *mocks.RsmWriterMock) {
+ logger, err := logger.InitLogger(logger.DebugLevel)
+ if err != nil {
+ t.Errorf("#... - failed to initialize logger, error: %s", err)
+ }
+
+ config, err := configuration.ParseConfiguration()
+ if err != nil {
+ t.Errorf("#... - failed to parse configuration error: %s", err)
+ }
+
+ converterMock := &mocks.ResourceStatusResponseConverterMock{}
+
+ rnibReaderMock := &mocks.RnibReaderMock{}
+ rsmReaderMock := &mocks.RsmReaderMock{}
+ rsmWriterMock := &mocks.RsmWriterMock{}
+
+ rnibDataService := services.NewRnibDataService(logger, config, rnibReaderMock, rsmReaderMock, rsmWriterMock)
+ h := NewResourceStatusResponseHandler(logger, converterMock, rnibDataService)
+
+ return converterMock, h, rsmReaderMock, rsmWriterMock
+
+}
+
+// Verify UnpackX2apPduAsString() and Convert() are called
+func TestResourceStatusResponseHandler(t *testing.T) {
+ converterMock, h, _, _ := initResourceStatusResponseHandlerTest(t)
+
+ payload := []byte("aaa")
+ req := models.RmrRequest{RanName: "test", StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ converterMock.On("UnpackX2apPduAsString", req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(string(payload), nil)
+ converterMock.On("Convert", req.Payload).Return((*models.ResourceStatusResponse)(nil), fmt.Errorf("error"))
+
+ h.Handle(&req)
+ converterMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ converterMock.AssertNumberOfCalls(t, "Convert", 1)
+}
+
+func TestResourceStatusResponseHandlerConvertError(t *testing.T) {
+ converterMock, h, _, _ := initResourceStatusResponseHandlerTest(t)
+
+ payload := []byte("aaa")
+ req := models.RmrRequest{RanName: "test", StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ err := fmt.Errorf("error")
+ var payloadAsString string
+ converterMock.On("UnpackX2apPduAsString", req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(payloadAsString, err)
+ converterMock.On("Convert", req.Payload).Return((*models.ResourceStatusResponse)(nil), fmt.Errorf("error"))
+ h.Handle(&req)
+
+ converterMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ converterMock.AssertNumberOfCalls(t, "Convert", 0)
+}
+
+func TestResourceStatusResponseHandlerEnb2Mid0(t *testing.T) {
+ converterMock, h, _, _ := initResourceStatusResponseHandlerTest(t)
+
+ payload := []byte("aaa")
+ req := models.RmrRequest{RanName: "test", StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ response := &models.ResourceStatusResponse{}
+ converterMock.On("UnpackX2apPduAsString", req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(string(payload), nil)
+ converterMock.On("Convert", req.Payload).Return(response, nil)
+ h.Handle(&req)
+
+ converterMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ converterMock.AssertNumberOfCalls(t, "Convert", 1)
+}
+
+func TestResourceStatusResponseHandlerWithMidGetRsmRanInfoFailure(t *testing.T) {
+ converterMock, h, rsmReaderMock, rsmWriterMock := initResourceStatusResponseHandlerTest(t)
+ payload := []byte("aaa")
+ req := models.RmrRequest{RanName: RanName, StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ response := &models.ResourceStatusResponse{ENB1_Measurement_ID: 1, ENB2_Measurement_ID: 2}
+ converterMock.On("UnpackX2apPduAsString", req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(string(payload), nil)
+ converterMock.On("Convert", req.Payload).Return(response, nil)
+ rsmReaderMock.On("GetRsmRanInfo", RanName).Return(&models.RsmRanInfo{}, common.NewInternalError(errors.New("Error")))
+ h.Handle(&req)
+ converterMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ converterMock.AssertNumberOfCalls(t, "Convert", 1)
+ rsmReaderMock.AssertCalled(t, "GetRsmRanInfo", RanName)
+ rsmWriterMock.AssertNotCalled(t, "SaveRsmRanInfo")
+}
+
+func TestResourceStatusResponseHandlerWithMidUpdateFailure(t *testing.T) {
+ converterMock, h, rsmReaderMock, rsmWriterMock := initResourceStatusResponseHandlerTest(t)
+ payload := []byte("aaa")
+ req := models.RmrRequest{RanName: RanName, StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ response := &models.ResourceStatusResponse{ENB1_Measurement_ID: 1, ENB2_Measurement_ID: 2}
+ converterMock.On("UnpackX2apPduAsString", req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(string(payload), nil)
+ converterMock.On("Convert", req.Payload).Return(response, nil)
+ rsmRanInfoBefore := models.NewRsmRanInfo(RanName, enums.Enb1MeasurementId, 0, enums.Start, false)
+ rsmReaderMock.On("GetRsmRanInfo", RanName).Return(rsmRanInfoBefore, nil)
+ updatedRsmRanInfo := models.NewRsmRanInfo(RanName, enums.Enb1MeasurementId, response.ENB2_Measurement_ID, enums.Start, true)
+ rsmWriterMock.On("SaveRsmRanInfo", rsmRanInfoBefore).Return(common.NewInternalError(errors.New("Error")))
+ h.Handle(&req)
+ converterMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ converterMock.AssertNumberOfCalls(t, "Convert", 1)
+ rsmReaderMock.AssertCalled(t, "GetRsmRanInfo", RanName)
+ rsmWriterMock.AssertCalled(t, "SaveRsmRanInfo", updatedRsmRanInfo)
+}
+
+func TestResourceStatusResponseHandlerWithMidSuccessfulUpdate(t *testing.T) {
+ converterMock, h, rsmReaderMock, rsmWriterMock := initResourceStatusResponseHandlerTest(t)
+ payload := []byte("aaa")
+ req := models.RmrRequest{RanName: RanName, StartTime: time.Now(), Payload: payload, Len: len(payload)}
+ response := &models.ResourceStatusResponse{ENB1_Measurement_ID: 1, ENB2_Measurement_ID: 2}
+ converterMock.On("UnpackX2apPduAsString", req.Payload, e2pdus.MaxAsn1CodecMessageBufferSize).Return(string(payload), nil)
+ converterMock.On("Convert", req.Payload).Return(response, nil)
+ rsmRanInfoBefore := models.NewRsmRanInfo(RanName, enums.Enb1MeasurementId, 0, enums.Start, false)
+ rsmReaderMock.On("GetRsmRanInfo", RanName).Return(rsmRanInfoBefore, nil)
+ updatedRsmRanInfo := models.NewRsmRanInfo(RanName, enums.Enb1MeasurementId, response.ENB2_Measurement_ID, enums.Start, true)
+ rsmWriterMock.On("SaveRsmRanInfo", rsmRanInfoBefore).Return(nil)
+ h.Handle(&req)
+ converterMock.AssertNumberOfCalls(t, "UnpackX2apPduAsString", 1)
+ converterMock.AssertNumberOfCalls(t, "Convert", 1)
+ rsmReaderMock.AssertCalled(t, "GetRsmRanInfo", RanName)
+ rsmWriterMock.AssertCalled(t, "SaveRsmRanInfo", updatedRsmRanInfo /*&updatedRsmRanInfo*/)
+}
type RmrMessageHandler interface {
Handle(*models.RmrRequest)
-}
\ No newline at end of file
+}
"rsm/controllers"
)
-func Run(port int, controller controllers.IRootController) error {
+func Run(port int, rootController controllers.IRootController, controller controllers.IController) error {
router := mux.NewRouter()
- initializeRoutes(router, controller)
+ initializeRoutes(router, rootController, controller)
addr := fmt.Sprintf(":%d", port)
return fmt.Errorf("#http_server.Run - Fail initiating HTTP server. Error: %v", err)
}
-func initializeRoutes(router *mux.Router, rootController controllers.IRootController) {
+func initializeRoutes(router *mux.Router, rootController controllers.IRootController, controller controllers.IController) {
r := router.PathPrefix("/v1").Subrouter()
r.HandleFunc("/health", rootController.HandleHealthCheckRequest).Methods("GET")
-}
+
+ rr := r.PathPrefix("/general").Subrouter()
+ rr.HandleFunc("/resourcestatus", controller.ResourceStatus).Methods("PUT")
+}
\ No newline at end of file
"time"
)
-func setupRouterAndMocks() (*mux.Router, *mocks.RootControllerMock) {
+func setupRouterAndMocks() (*mux.Router, *mocks.RootControllerMock, *mocks.ControllerMock) {
rootControllerMock := &mocks.RootControllerMock{}
rootControllerMock.On("HandleHealthCheckRequest").Return(nil)
+ controllerMock := &mocks.ControllerMock{}
+ controllerMock.On("ResourceStatus").Return(nil)
+
router := mux.NewRouter()
- initializeRoutes(router, rootControllerMock)
- return router, rootControllerMock
+ initializeRoutes(router, rootControllerMock, controllerMock)
+ return router, rootControllerMock, controllerMock
+}
+func TestResourceStatus(t *testing.T) {
+ router, _, controllerMock := setupRouterAndMocks()
+
+ req, err := http.NewRequest("PUT", "/v1/general/resourcestatus", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ rr := httptest.NewRecorder()
+ router.ServeHTTP(rr, req)
+
+ controllerMock.AssertNumberOfCalls(t, "ResourceStatus", 1)
}
func TestRouteGetHealth(t *testing.T) {
- router, rootControllerMock := setupRouterAndMocks()
+ router, rootControllerMock, _ := setupRouterAndMocks()
req, err := http.NewRequest("GET", "/v1/health", nil)
if err != nil {
}
func TestRouteNotFound(t *testing.T) {
- router, _ := setupRouterAndMocks()
+ router, _, _ := setupRouterAndMocks()
req, err := http.NewRequest("GET", "/v1/no/such/route", nil)
if err != nil {
}
func TestRunError(t *testing.T) {
- rootControllerMock := &mocks.RootControllerMock{}
+ _, rootControllerMock, controllerMock := setupRouterAndMocks()
- err := Run(111222333, rootControllerMock)
+ err := Run(111222333, rootControllerMock, controllerMock)
assert.NotNil(t, err)
}
func TestRun(t *testing.T) {
- rootControllerMock := &mocks.RootControllerMock{}
- rootControllerMock.On("HandleHealthCheckRequest").Return(nil)
+ _, rootControllerMock, controllerMock := setupRouterAndMocks()
- go Run(11223, rootControllerMock)
+ go Run(11223, rootControllerMock, controllerMock)
time.Sleep(time.Millisecond * 100)
resp, err := http.Get("http://localhost:11223/v1/health")
)
type Logger struct {
- Logger *zap.Logger
+ Logger *zap.Logger
}
// Copied from zap logger
_maxLevel = FatalLevel
)
-var logLevelTokenToLevel = map[string] LogLevel {
- "debug" : DebugLevel,
- "info": InfoLevel,
- "warn": WarnLevel,
- "error": ErrorLevel,
+var logLevelTokenToLevel = map[string]LogLevel{
+ "debug": DebugLevel,
+ "info": InfoLevel,
+ "warn": WarnLevel,
+ "error": ErrorLevel,
"dpanic": DPanicLevel,
- "panic": PanicLevel,
- "fatal": FatalLevel,
+ "panic": PanicLevel,
+ "fatal": FatalLevel,
}
func LogLevelTokenToLevel(level string) (LogLevel, bool) {
- if level, ok := logLevelTokenToLevel[strings.TrimSpace(strings.ToLower(level))];ok {
+ if level, ok := logLevelTokenToLevel[strings.TrimSpace(strings.ToLower(level))]; ok {
return level, true
}
- return _maxLevel+1, false
+ return _maxLevel + 1, false
}
func InitLogger(requested LogLevel) (*Logger, error) {
case FatalLevel:
logger, err = initLoggerByLevel(zapcore.FatalLevel)
default:
- err = fmt.Errorf("Invalid logging Level :%d",requested)
+ err = fmt.Errorf("invalid logging Level :%d", requested)
}
if err != nil {
return nil, err
}
- return &Logger{Logger:logger}, nil
+ return &Logger{Logger: logger}, nil
}
-func(l *Logger)Sync() error {
+func (l *Logger) Sync() error {
l.Debugf("#logger.Sync - Going to flush buffered log")
return l.Logger.Sync()
}
-func (l *Logger)Infof(formatMsg string, a ...interface{}) {
+func (l *Logger) Infof(formatMsg string, a ...interface{}) {
if l.InfoEnabled() {
msg := fmt.Sprintf(formatMsg, a...)
l.Logger.Info(msg, zap.Any("mdc", l.getTimeStampMdc()))
}
}
-func (l *Logger)Debugf(formatMsg string, a ...interface{}) {
- if l.DebugEnabled(){
+func (l *Logger) Debugf(formatMsg string, a ...interface{}) {
+ if l.DebugEnabled() {
msg := fmt.Sprintf(formatMsg, a...)
l.Logger.Debug(msg, zap.Any("mdc", l.getTimeStampMdc()))
}
}
-func (l *Logger)Errorf(formatMsg string, a ...interface{}) {
+func (l *Logger) Errorf(formatMsg string, a ...interface{}) {
msg := fmt.Sprintf(formatMsg, a...)
l.Logger.Error(msg, zap.Any("mdc", l.getTimeStampMdc()))
}
-func (l *Logger)Warnf(formatMsg string, a ...interface{}) {
+func (l *Logger) Warnf(formatMsg string, a ...interface{}) {
msg := fmt.Sprintf(formatMsg, a...)
l.Logger.Warn(msg, zap.Any("mdc", l.getTimeStampMdc()))
}
return mdc
}
-func (l *Logger)InfoEnabled()bool{
+func (l *Logger) InfoEnabled() bool {
return l.Logger.Core().Enabled(zap.InfoLevel)
}
-func (l *Logger)DebugEnabled()bool{
+func (l *Logger) DebugEnabled() bool {
return l.Logger.Core().Enabled(zap.DebugLevel)
}
-func (l *Logger)DPanicf(formatMsg string, a ...interface{}) {
+func (l *Logger) DPanicf(formatMsg string, a ...interface{}) {
msg := fmt.Sprintf(formatMsg, a...)
l.Logger.DPanic(msg, zap.Any("mdc", l.getTimeStampMdc()))
}
millis := int64(nanos) / int64(time.Millisecond)
enc.AppendInt64(millis)
}
-
assert.Nil(t, log)
}
-func TestSyncSuccess(t *testing.T){
+func TestSyncSuccess(t *testing.T) {
logFile, err := os.Create("./loggerTest.txt")
- if err != nil{
+ if err != nil {
t.Errorf("logger_test.TestSyncSuccess - failed to create file, error: %s", err)
}
old := os.Stdout
os.Stdout = old
logFile, err = os.Open("./loggerTest.txt")
- if err != nil{
+ if err != nil {
t.Errorf("logger_test.TestSyncSuccess - failed to open file, error: %s", err)
}
var buf bytes.Buffer
if err != nil {
t.Errorf("logger_test.TestSyncSuccess - failed to copy bytes, error: %s", err)
}
- debugRecord,_ :=buf.ReadString('\n')
- errorRecord,_ :=buf.ReadString('\n')
+ debugRecord, _ := buf.ReadString('\n')
+ errorRecord, _ := buf.ReadString('\n')
assert.NotEmpty(t, debugRecord)
assert.Empty(t, errorRecord)
}
-func TestSyncFailure(t *testing.T){
+func TestSyncFailure(t *testing.T) {
log, err := InitLogger(DebugLevel)
err = log.Sync()
assert.NotNil(t, err)
}
-func TestDebugEnabledFalse(t *testing.T){
+func TestDebugEnabledFalse(t *testing.T) {
entryNum, log := countRecords(InfoLevel, t)
assert.False(t, log.DebugEnabled())
- assert.Equal(t,3, entryNum)
+ assert.Equal(t, 3, entryNum)
}
-func TestDebugEnabledTrue(t *testing.T){
+func TestDebugEnabledTrue(t *testing.T) {
entryNum, log := countRecords(DebugLevel, t)
assert.True(t, log.DebugEnabled())
- assert.Equal(t,4, entryNum)
+ assert.Equal(t, 4, entryNum)
}
-func TestDPanicfDebugLevel(t *testing.T){
- assert.True(t,validateRecordExists(DebugLevel, zap.DPanicLevel, t))
+func TestDPanicfDebugLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(DebugLevel, zap.DPanicLevel, t))
}
-func TestDPanicfInfoLevel(t *testing.T){
- assert.True(t,validateRecordExists(InfoLevel, zap.DPanicLevel, t))
+func TestDPanicfInfoLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(InfoLevel, zap.DPanicLevel, t))
}
-func TestErrorfDebugLevel(t *testing.T) {
- assert.True(t,validateRecordExists(DebugLevel, zap.ErrorLevel, t))
+func TestErrorfDebugLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(DebugLevel, zap.ErrorLevel, t))
}
-func TestErrorfInfoLevel(t *testing.T) {
- assert.True(t,validateRecordExists(InfoLevel, zap.ErrorLevel, t))
+func TestErrorfInfoLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(InfoLevel, zap.ErrorLevel, t))
}
-func TestInfofDebugLevel(t *testing.T) {
- assert.True(t,validateRecordExists(DebugLevel, zap.InfoLevel, t))
+func TestInfofDebugLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(DebugLevel, zap.InfoLevel, t))
}
-func TestInfofInfoLevel(t *testing.T) {
- assert.True(t,validateRecordExists(InfoLevel, zap.InfoLevel, t))
+func TestInfofInfoLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(InfoLevel, zap.InfoLevel, t))
}
-func TestDebugfDebugLevel(t *testing.T) {
- assert.True(t,validateRecordExists(DebugLevel, zap.DebugLevel, t))
+func TestDebugfDebugLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(DebugLevel, zap.DebugLevel, t))
}
-func TestDebugfInfoLevel(t *testing.T) {
- assert.False(t,validateRecordExists(InfoLevel, zap.DebugLevel, t))
+func TestDebugfInfoLevel(t *testing.T) {
+ assert.False(t, validateRecordExists(InfoLevel, zap.DebugLevel, t))
}
-func TestInfofFatalLevel(t *testing.T) {
- assert.False(t,validateRecordExists(FatalLevel, zap.InfoLevel, t))
+func TestInfofFatalLevel(t *testing.T) {
+ assert.False(t, validateRecordExists(FatalLevel, zap.InfoLevel, t))
}
-func TestDebugfFatalLevel(t *testing.T) {
- assert.False(t,validateRecordExists(FatalLevel, zap.DebugLevel, t))
+func TestDebugfFatalLevel(t *testing.T) {
+ assert.False(t, validateRecordExists(FatalLevel, zap.DebugLevel, t))
}
-func TestWarnfWarnLevel(t *testing.T) {
- assert.True(t,validateRecordExists(WarnLevel, zap.WarnLevel, t))
+func TestWarnfWarnLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(WarnLevel, zap.WarnLevel, t))
}
-func TestWarnfDebugLevel(t *testing.T) {
- assert.True(t,validateRecordExists(DebugLevel, zap.WarnLevel, t))
+func TestWarnfDebugLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(DebugLevel, zap.WarnLevel, t))
}
-func TestWarnfInfoLevel(t *testing.T) {
- assert.True(t,validateRecordExists(InfoLevel, zap.WarnLevel, t))
+func TestWarnfInfoLevel(t *testing.T) {
+ assert.True(t, validateRecordExists(InfoLevel, zap.WarnLevel, t))
}
-func TestWarnfFatalLevel(t *testing.T) {
- assert.False(t,validateRecordExists(FatalLevel, zap.WarnLevel, t))
+func TestWarnfFatalLevel(t *testing.T) {
+ assert.False(t, validateRecordExists(FatalLevel, zap.WarnLevel, t))
}
func TestLogLevelTokenToLevel(t *testing.T) {
assert.True(t, level > FatalLevel)
}
-func countRecords(logLevel LogLevel, t *testing.T) (int, *Logger){
+func countRecords(logLevel LogLevel, t *testing.T) (int, *Logger) {
old := os.Stdout
- r, w, _ :=os.Pipe()
+ r, w, _ := os.Pipe()
os.Stdout = w
log, err := InitLogger(logLevel)
if err != nil {
t.Errorf("logger_test.TestSyncFailure - failed to copy bytes, error: %s", err)
}
entryNum := 0
- s,_:= buf.ReadString('\n')
- for len(s) > 0{
- entryNum +=1
- s,_= buf.ReadString('\n')
+ s, _ := buf.ReadString('\n')
+ for len(s) > 0 {
+ entryNum += 1
+ s, _ = buf.ReadString('\n')
}
return entryNum, log
}
func validateRecordExists(logLevel LogLevel, recordLevel zapcore.Level, t *testing.T) bool {
old := os.Stdout
- r, w, _ :=os.Pipe()
+ r, w, _ := os.Pipe()
os.Stdout = w
log, err := InitLogger(logLevel)
if err != nil {
t.Errorf("logger_test.TestSyncFailure - failed to initialize logger, error: %s", err)
}
- switch recordLevel{
- case zap.DebugLevel:
+ switch recordLevel {
+ case zap.DebugLevel:
log.Debugf("%v, %v, %v", 1, "abc", 0.1)
case zap.InfoLevel:
log.Infof("%v, %v, %v", 1, "abc", 0.1)
t.Errorf("logger_test.TestSyncFailure - failed to copy bytes, error: %s", err)
}
entryNum := 0
- s,_:= buf.ReadString('\n')
- for len(s) > 0{
- entryNum +=1
- s,_= buf.ReadString('\n')
+ s, _ := buf.ReadString('\n')
+ for len(s) > 0 {
+ entryNum += 1
+ s, _ = buf.ReadString('\n')
}
return entryNum == 1
-}
\ No newline at end of file
+}
+++ /dev/null
-package managers
-
-import (
- "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
- "rsm/e2pdus"
- "rsm/enums"
- "rsm/logger"
- "rsm/models"
- "rsm/rmrcgo"
- "rsm/rsmerrors"
- "rsm/services"
- "rsm/services/rmrsender"
-)
-
-type ResourceStatusInitiateManager struct {
- logger *logger.Logger
- rnibDataService services.RNibDataService
- rmrSender *rmrsender.RmrSender
-}
-
-type IResourceStatusInitiateManager interface {
- Execute(inventoryName string, resourceStatusInitiateRequestParams *e2pdus.ResourceStatusRequestData) error
-}
-
-func NewResourceStatusInitiateManager(logger *logger.Logger, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender) *ResourceStatusInitiateManager {
- return &ResourceStatusInitiateManager{
- logger: logger,
- rnibDataService: rnibDataService,
- rmrSender: rmrSender,
- }
-}
-
-func (m *ResourceStatusInitiateManager) Execute(inventoryName string, resourceStatusInitiateRequestParams *e2pdus.ResourceStatusRequestData) error {
-
- nodebInfo, err := m.rnibDataService.GetNodeb(inventoryName)
-
- if err != nil {
- m.logger.Errorf("#ResourceStatusInitiateManager.Execute - RAN name: %s - Error fetching RAN from rNib: %v", inventoryName, err)
- return rsmerrors.NewRnibDbError()
- }
-
- m.logger.Infof("#ResourceStatusInitiateManager.Execute - RAN name: %s, connection status: %s", nodebInfo.GetRanName(), nodebInfo.GetConnectionStatus())
-
- if nodebInfo.GetConnectionStatus() != entities.ConnectionStatus_CONNECTED {
- m.logger.Errorf("#ResourceStatusInitiateManager.Execute - RAN name: %s - RAN's connection status isn't CONNECTED", inventoryName)
- return rsmerrors.NewWrongStateError("Resource Status Initiate", entities.ConnectionStatus_name[int32(nodebInfo.ConnectionStatus)])
- }
-
- m.sendResourceStatusInitiatePerCell(nodebInfo, *resourceStatusInitiateRequestParams)
-
- return nil
-}
-
-func (m *ResourceStatusInitiateManager) sendResourceStatusInitiatePerCell(nodebInfo *entities.NodebInfo, requestParams e2pdus.ResourceStatusRequestData) {
- enb, _ := nodebInfo.Configuration.(*entities.NodebInfo_Enb)
- cells := enb.Enb.ServedCells
-
- for index, cellInfo := range cells {
- requestParams.CellID = cellInfo.CellId
- requestParams.MeasurementID = e2pdus.Measurement_ID(index + 1)
-
- m.logger.Infof("#ResourceStatusInitiateManager.sendResourceStatusInitiatePerCell - RAN name: %s, Going to send request for cell id %s, measurement id %d", nodebInfo.RanName, requestParams.CellID, requestParams.MeasurementID)
-
- payload, payloadAsString, err := e2pdus.BuildPackedResourceStatusRequest(enums.Registration_Request_start, &requestParams, e2pdus.MaxAsn1PackedBufferSize, e2pdus.MaxAsn1CodecMessageBufferSize, m.logger.DebugEnabled())
- if err != nil {
- m.logger.Errorf("#ResourceStatusInitiateManager.sendResourceStatusInitiatePerCell - RAN name: %s. Failed to build and pack the resource status initiate request for cell id %s, measurement id %d. error: %s", nodebInfo.RanName, requestParams.CellID, requestParams.MeasurementID, err)
- continue
- }
-
- m.logger.Debugf("#ResourceStatusInitiateManager.sendResourceStatusInitiatePerCell - RAN name: %s, cell id: %s, measurement id: %d, payload: %s", nodebInfo.RanName, requestParams.CellID, requestParams.MeasurementID, payloadAsString)
-
- rmrMsg := models.NewRmrMessage(rmrcgo.RicResStatusReq, nodebInfo.RanName, payload)
- go m.rmrSender.Send(rmrMsg)
- }
-}
+++ /dev/null
-package managers
-
-import (
- "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
- "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
- "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
- "github.com/pkg/errors"
- "github.com/stretchr/testify/assert"
- "rsm/configuration"
- "rsm/e2pdus"
- "rsm/enums"
- "rsm/logger"
- "rsm/mocks"
- "rsm/rmrcgo"
- "rsm/rsmerrors"
- "rsm/services"
- "rsm/tests/testhelper"
- "testing"
- "time"
-)
-
-const RanName = "test"
-
-func initResourceStatusInitiateManagerTest(t *testing.T) (*mocks.RmrMessengerMock, *mocks.RnibReaderMock, *e2pdus.ResourceStatusRequestData, *ResourceStatusInitiateManager) {
- logger, err := logger.InitLogger(logger.InfoLevel)
- if err != nil {
- t.Errorf("#... - failed to initialize logger, error: %s", err)
- }
-
- config, err := configuration.ParseConfiguration()
- if err != nil {
- t.Errorf("#... - failed to parse configuration error: %s", err)
- }
-
- rmrMessengerMock := &mocks.RmrMessengerMock{}
- rmrSender := testhelper.InitRmrSender(rmrMessengerMock, logger)
-
- readerMock := &mocks.RnibReaderMock{}
- rnibReaderProvider := func() reader.RNibReader {
- return readerMock
- }
-
- resourceStatusRequestData := &e2pdus.ResourceStatusRequestData{}
- populateResourceStatusInitiateRequestParams(resourceStatusRequestData, config)
-
- rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider)
- resourceStatusInitiateManager := NewResourceStatusInitiateManager(logger, rnibDataService, rmrSender)
- return rmrMessengerMock, readerMock, resourceStatusRequestData, resourceStatusInitiateManager
-}
-
-func TestGetNodebFailure(t *testing.T) {
- rmrMessengerMock, readerMock, resourceStatusInitiateRequestParams, resourceStatusInitiateManager := initResourceStatusInitiateManagerTest(t)
- var nodebInfo *entities.NodebInfo
- readerMock.On("GetNodeb", RanName).Return(nodebInfo, common.NewInternalError(errors.New("Error")))
- err := resourceStatusInitiateManager.Execute(RanName, resourceStatusInitiateRequestParams)
- readerMock.AssertCalled(t, "GetNodeb", RanName)
- assert.IsType(t, &rsmerrors.RnibDbError{}, err)
- rmrMessengerMock.AssertNotCalled(t, "SendMsg")
-}
-
-func TestInvalidConnectionStatus(t *testing.T) {
- rmrMessengerMock, readerMock, resourceStatusInitiateRequestParams, resourceStatusInitiateManager := initResourceStatusInitiateManagerTest(t)
- var err error
- readerMock.On("GetNodeb", RanName).Return(&entities.NodebInfo{ConnectionStatus: entities.ConnectionStatus_DISCONNECTED}, err)
- err = resourceStatusInitiateManager.Execute(RanName, resourceStatusInitiateRequestParams)
- readerMock.AssertCalled(t, "GetNodeb", RanName)
- assert.IsType(t, &rsmerrors.WrongStateError{}, err)
- rmrMessengerMock.AssertNotCalled(t, "SendMsg")
-}
-
-func TestPackFailure(t *testing.T) {
- rmrMessengerMock, readerMock, resourceRequestData, resourceStatusInitiateManager := initResourceStatusInitiateManagerTest(t)
- var err error
- nodebInfo := &entities.NodebInfo{
- RanName: RanName,
- ConnectionStatus: entities.ConnectionStatus_CONNECTED,
- Configuration: &entities.NodebInfo_Enb{
- Enb: &entities.Enb{
- ServedCells: []*entities.ServedCellInfo{{CellId: ""}},
- },
- },
- }
-
- readerMock.On("GetNodeb", RanName).Return(nodebInfo, err)
- err = resourceStatusInitiateManager.Execute(RanName, resourceRequestData)
- assert.Nil(t, err)
- readerMock.AssertCalled(t, "GetNodeb", RanName)
- rmrMessengerMock.AssertNotCalled(t, "SendMsg")
-}
-
-func TestOneCellSuccess(t *testing.T) {
- cellId := "02f829:0007ab00"
- rmrMessengerMock, readerMock, resourceRequestData, resourceStatusInitiateManager := initResourceStatusInitiateManagerTest(t)
- xaction := []byte(RanName)
- var err error
- nodebInfo := &entities.NodebInfo{
- RanName: RanName,
- ConnectionStatus: entities.ConnectionStatus_CONNECTED,
- Configuration: &entities.NodebInfo_Enb{
- Enb: &entities.Enb{
- ServedCells: []*entities.ServedCellInfo{{CellId: cellId}},
- },
- },
- }
-
- readerMock.On("GetNodeb", RanName).Return(nodebInfo, err)
- expectedPayload := getPackedPayloadForCell(cellId, 1, *resourceRequestData)
- expectedMbuf := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload), RanName, &expectedPayload, &xaction)
- rmrMessengerMock.On("SendMsg", expectedMbuf).Return(&rmrcgo.MBuf{}, err)
- err = resourceStatusInitiateManager.Execute(RanName, resourceRequestData)
- time.Sleep(100 * time.Millisecond)
- readerMock.AssertCalled(t, "GetNodeb", RanName)
- assert.Nil(t, err)
- rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf)
- rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 1)
-}
-
-func TestTwoCellOneFailureOneSuccess(t *testing.T) {
- cellId1 := "02f829:0007ab00"
- cellId2 := "02f829:0007ab50"
- rmrMessengerMock, readerMock, resourceRequestData, resourceStatusInitiateManager := initResourceStatusInitiateManagerTest(t)
- xaction := []byte(RanName)
- var err error
- nodebInfo := &entities.NodebInfo{
- RanName: RanName,
- ConnectionStatus: entities.ConnectionStatus_CONNECTED,
- Configuration: &entities.NodebInfo_Enb{
- Enb: &entities.Enb{
- ServedCells: []*entities.ServedCellInfo{{CellId: cellId1}, {CellId: cellId2}},
- },
- },
- }
-
- readerMock.On("GetNodeb", RanName).Return(nodebInfo, err)
- expectedPayload1 := getPackedPayloadForCell(cellId1, 1, *resourceRequestData)
- expectedMbuf1 := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload1), RanName, &expectedPayload1, &xaction)
-
- expectedPayload2 := getPackedPayloadForCell(cellId2, 2, *resourceRequestData)
- expectedMbuf2 := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload2), RanName, &expectedPayload2, &xaction)
- rmrMessengerMock.On("SendMsg", expectedMbuf1).Return(&rmrcgo.MBuf{}, rsmerrors.NewRmrError())
- rmrMessengerMock.On("SendMsg", expectedMbuf2).Return(&rmrcgo.MBuf{}, err)
- err = resourceStatusInitiateManager.Execute(RanName, resourceRequestData)
- time.Sleep(100 * time.Millisecond)
- readerMock.AssertCalled(t, "GetNodeb", RanName)
- assert.Nil(t, err)
- rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf1)
- rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf2)
- rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 2)
-}
-
-func TestFiveCellsSuccess(t *testing.T) {
- cellId1 := "02f829:0007ab00"
- cellId2 := "02f829:0007ab50"
- cellId3 := "02f829:0007ab60"
- cellId4 := "02f829:0007ab70"
- cellId5 := "02f829:0007ab80"
-
- rmrMessengerMock, readerMock, resourceRequestData, resourceStatusInitiateManager := initResourceStatusInitiateManagerTest(t)
- xaction := []byte(RanName)
- var err error
- nodebInfo := &entities.NodebInfo{
- RanName: RanName,
- ConnectionStatus: entities.ConnectionStatus_CONNECTED,
- Configuration: &entities.NodebInfo_Enb{
- Enb: &entities.Enb{
- ServedCells: []*entities.ServedCellInfo{{CellId: cellId1}, {CellId: cellId2}, {CellId: cellId3}, {CellId: cellId4}, {CellId: cellId5}},
- },
- },
- }
-
- readerMock.On("GetNodeb", RanName).Return(nodebInfo, err)
- expectedPayload1 := getPackedPayloadForCell(cellId1, 1, *resourceRequestData)
- expectedMbuf1 := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload1), RanName, &expectedPayload1, &xaction)
-
- expectedPayload2 := getPackedPayloadForCell(cellId2, 2, *resourceRequestData)
- expectedMbuf2 := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload2), RanName, &expectedPayload2, &xaction)
-
- expectedPayload3 := getPackedPayloadForCell(cellId3, 3, *resourceRequestData)
- expectedMbuf3 := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload3), RanName, &expectedPayload3, &xaction)
-
- expectedPayload4 := getPackedPayloadForCell(cellId4, 4, *resourceRequestData)
- expectedMbuf4 := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload4), RanName, &expectedPayload4, &xaction)
-
- expectedPayload5 := getPackedPayloadForCell(cellId5, 5, *resourceRequestData)
- expectedMbuf5 := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload5), RanName, &expectedPayload5, &xaction)
-
- rmrMessengerMock.On("SendMsg", expectedMbuf1).Return(&rmrcgo.MBuf{}, err)
- rmrMessengerMock.On("SendMsg", expectedMbuf2).Return(&rmrcgo.MBuf{}, err)
- rmrMessengerMock.On("SendMsg", expectedMbuf3).Return(&rmrcgo.MBuf{}, err)
- rmrMessengerMock.On("SendMsg", expectedMbuf4).Return(&rmrcgo.MBuf{}, err)
- rmrMessengerMock.On("SendMsg", expectedMbuf5).Return(&rmrcgo.MBuf{}, err)
-
- err = resourceStatusInitiateManager.Execute(RanName, resourceRequestData)
- time.Sleep(100 * time.Millisecond)
- readerMock.AssertCalled(t, "GetNodeb", RanName)
- assert.Nil(t, err)
- rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf1)
- rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf2)
- rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf3)
- rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf4)
- rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf5)
-
- rmrMessengerMock.AssertNumberOfCalls(t, "SendMsg", 5)
-}
-
-func getPackedPayloadForCell(cellId string, index int, resourceStatusRequestData e2pdus.ResourceStatusRequestData) []byte {
- resourceStatusRequestData.CellID = cellId
- resourceStatusRequestData.MeasurementID = e2pdus.Measurement_ID(index)
- expectedPayload, _, _ := e2pdus.BuildPackedResourceStatusRequest(enums.Registration_Request_start, &resourceStatusRequestData, e2pdus.MaxAsn1PackedBufferSize, e2pdus.MaxAsn1CodecMessageBufferSize, false)
- return expectedPayload
-}
-
-func populateResourceStatusInitiateRequestParams(params *e2pdus.ResourceStatusRequestData, config *configuration.Configuration) {
- params.PartialSuccessAllowed = config.ResourceStatusParams.PartialSuccessAllowed
- params.PrbPeriodic = config.ResourceStatusParams.PrbPeriodic
- params.TnlLoadIndPeriodic = config.ResourceStatusParams.TnlLoadIndPeriodic
- params.HwLoadIndPeriodic = config.ResourceStatusParams.HwLoadIndPeriodic
- params.AbsStatusPeriodic = config.ResourceStatusParams.AbsStatusPeriodic
- params.RsrpMeasurementPeriodic = config.ResourceStatusParams.RsrpMeasurementPeriodic
- params.CsiPeriodic = config.ResourceStatusParams.CsiPeriodic
- params.PeriodicityMS = config.ResourceStatusParams.PeriodicityMs
- params.PeriodicityRsrpMeasurementMS = config.ResourceStatusParams.PeriodicityRsrpMeasurementMs
- params.PeriodicityCsiMS = config.ResourceStatusParams.PeriodicityCsiMs
-}
"rsm/configuration"
"rsm/converters"
"rsm/logger"
- "rsm/managers"
"rsm/models"
"rsm/providers/rmrmsghandlerprovider"
"rsm/rmrcgo"
handlerProvider *rmrmsghandlerprovider.MessageHandlerProvider
}
-func NewRmrMessageManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, resourceStatusInitiateManager *managers.ResourceStatusInitiateManager, unpacker converters.Asn1PduUnpacker) *RmrMessageManager {
- handlerProvider := rmrmsghandlerprovider.NewMessageHandlerProvider(logger,config, rnibDataService, rmrSender, resourceStatusInitiateManager, unpacker)
+func NewRmrMessageManager(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, resourceStatusService *services.ResourceStatusService, rsConverter converters.ResourceStatusResponseConverter, rsFailureConverter converters.ResourceStatusFailureConverter) *RmrMessageManager {
+ handlerProvider := rmrmsghandlerprovider.NewMessageHandlerProvider(logger, config, rnibDataService, rmrSender, resourceStatusService, rsConverter, rsFailureConverter)
return &RmrMessageManager{
handlerProvider: handlerProvider,
- logger: logger,
+ logger: logger,
}
}
import (
"rsm/configuration"
- "rsm/managers"
+ "rsm/converters"
+ "rsm/e2pdus"
"rsm/rmrcgo"
+ "rsm/services"
"rsm/tests/testhelper"
"testing"
)
rnibDataService, rmrSender, logger := testhelper.InitTestCase(t)
config, _ := configuration.ParseConfiguration()
- resourceStatusInitiateManager := managers.NewResourceStatusInitiateManager(logger, rnibDataService, rmrSender)
-
- manager := NewRmrMessageManager(logger, config, rnibDataService, rmrSender, resourceStatusInitiateManager, nil)
+ resourceStatusService := services.NewResourceStatusService(logger, rmrSender)
+ unpacker := converters.NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ manager := NewRmrMessageManager(logger, config, rnibDataService, rmrSender, resourceStatusService, converters.NewResourceStatusResponseConverter(unpacker), converters.NewResourceStatusFailureConverter(unpacker))
xactionByteArr := []byte("1111111")
payloadByteArr := []byte("payload")
rnibDataService, rmrSender, logger := testhelper.InitTestCase(t)
config, _ := configuration.ParseConfiguration()
- resourceStatusInitiateManager := managers.NewResourceStatusInitiateManager(logger, rnibDataService, rmrSender)
-
- manager := NewRmrMessageManager(logger, config, rnibDataService, rmrSender, resourceStatusInitiateManager, nil)
+ resourceStatusService := services.NewResourceStatusService(logger, rmrSender)
+ unpacker := converters.NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ manager := NewRmrMessageManager(logger, config, rnibDataService, rmrSender, resourceStatusService, converters.NewResourceStatusResponseConverter(unpacker), converters.NewResourceStatusFailureConverter(unpacker))
xactionByteArr := []byte("1111111")
payloadByteArr := []byte("payload")
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 mocks
import (
"github.com/stretchr/testify/mock"
+ "net/http"
)
type ControllerMock struct {
mock.Mock
}
+
+func (c *ControllerMock) ResourceStatus(writer http.ResponseWriter, r *http.Request){
+ writer.Header().Set("Content-Type", "application/json")
+ writer.WriteHeader(http.StatusOK)
+
+ c.Called()
+}
\ No newline at end of file
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 mocks
+
+import (
+ "github.com/stretchr/testify/mock"
+ "rsm/models"
+)
+
+type ResourceStatusFailureConverterMock struct {
+ mock.Mock
+}
+
+func (m *ResourceStatusFailureConverterMock) Convert(packedBuf []byte) (*models.ResourceStatusResponse, error) {
+ args := m.Called(packedBuf)
+ return args.Get(0).(*models.ResourceStatusResponse), args.Error(1)
+}
+
+func (m *ResourceStatusFailureConverterMock) UnpackX2apPduAsString(packedBuf []byte, maxMessageBufferSize int) (string, error) {
+ args := m.Called(packedBuf, maxMessageBufferSize)
+ return args.Get(0).(string), args.Error(1)
+}
+++ /dev/null
-package mocks
-
-import (
- "github.com/stretchr/testify/mock"
- "rsm/e2pdus"
-)
-
-type ResourceStatusInitiateManagerMock struct {
- mock.Mock
-}
-
-func (m *ResourceStatusInitiateManagerMock) Execute(inventoryName string, resourceStatusInitiateRequestParams *e2pdus.ResourceStatusRequestData) error {
- args := m.Called(inventoryName, resourceStatusInitiateRequestParams)
- return args.Error(0)
-}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 mocks
+
+import (
+ "github.com/stretchr/testify/mock"
+ "rsm/models"
+)
+
+type ResourceStatusResponseConverterMock struct {
+ mock.Mock
+}
+
+func (m *ResourceStatusResponseConverterMock) Convert(packedBuf []byte) (*models.ResourceStatusResponse, error) {
+ args := m.Called(packedBuf)
+ return args.Get(0).(*models.ResourceStatusResponse), args.Error(1)
+}
+
+func (m *ResourceStatusResponseConverterMock) UnpackX2apPduAsString(packedBuf []byte, maxMessageBufferSize int) (string, error) {
+ args := m.Called(packedBuf, maxMessageBufferSize)
+ return args.Get(0).(string), args.Error(1)
+}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 mocks
+
+import (
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "github.com/stretchr/testify/mock"
+ "rsm/models"
+)
+
+type ResourceStatusServiceMock struct {
+ mock.Mock
+}
+
+func (m *ResourceStatusServiceMock) BuildAndSendInitiateRequest(nodeb *entities.NodebInfo, config *models.RsmGeneralConfiguration, enb1MeasurementId int64) error {
+ args := m.Called(nodeb, config, enb1MeasurementId)
+ return args.Error(0)
+}
+
+func (m *ResourceStatusServiceMock) BuildAndSendStopRequest(nodeb *entities.NodebInfo, config *models.RsmGeneralConfiguration, enb1MeasurementId int64, enb2MeasurementId int64) error {
+ args := m.Called(nodeb, config, enb1MeasurementId, enb2MeasurementId)
+ return args.Error(0)
+}
\ No newline at end of file
mock.Mock
}
-func (m *RmrMessengerMock) Init(readyIntervalSec int, port string, maxMsgSize int, flags int, logger *logger.Logger) rmrcgo.RmrMessenger{
+func (m *RmrMessengerMock) Init(readyIntervalSec int, port string, maxMsgSize int, flags int, logger *logger.Logger) rmrcgo.RmrMessenger {
args := m.Called(readyIntervalSec, port, maxMsgSize, flags, logger)
return args.Get(0).(rmrcgo.RmrMessenger)
}
-func (m *RmrMessengerMock) SendMsg(msg *rmrcgo.MBuf) (*rmrcgo.MBuf, error){
+func (m *RmrMessengerMock) SendMsg(msg *rmrcgo.MBuf) (*rmrcgo.MBuf, error) {
args := m.Called(msg)
return args.Get(0).(*rmrcgo.MBuf), args.Error(1)
}
-func (m *RmrMessengerMock) RecvMsg() (*rmrcgo.MBuf, error){
- args := m.Called( )
+func (m *RmrMessengerMock) RecvMsg() (*rmrcgo.MBuf, error) {
+ args := m.Called()
return args.Get(0).(*rmrcgo.MBuf), args.Error(1)
}
-func (m *RmrMessengerMock) RtsMsg(msg *rmrcgo.MBuf){
- m.Called( )
+func (m *RmrMessengerMock) RtsMsg(msg *rmrcgo.MBuf) {
+ m.Called()
}
-func (m *RmrMessengerMock) FreeMsg(){
- m.Called( )
+func (m *RmrMessengerMock) FreeMsg() {
+ m.Called()
}
-func (m *RmrMessengerMock) IsReady() bool{
- args := m.Called( )
+func (m *RmrMessengerMock) IsReady() bool {
+ args := m.Called()
return args.Bool(0)
}
-func (m *RmrMessengerMock) Close(){
- m.Called( )
-}
\ No newline at end of file
+func (m *RmrMessengerMock) Close() {
+ m.Called()
+}
return args.Get(0).(*entities.RanLoadInformation), nil
}
+
+func (m *RnibReaderMock) GetE2TInstance(e2taddress string) (*entities.E2TInstance, error) {
+ args := m.Called(e2taddress)
+ return args.Get(0).(*entities.E2TInstance), args.Error(1)
+}
+
+func (m *RnibReaderMock) GetE2TInstances(addresses []string) ([]*entities.E2TInstance, error) {
+ args := m.Called(addresses)
+ return args.Get(0).([]*entities.E2TInstance), args.Error(1)
+}
+
+func (m *RnibReaderMock) GetE2TAddresses() ([]string, error) {
+ args := m.Called()
+ return args.Get(0).([]string), args.Error(1)
+}
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 mocks
import (
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 mocks
+
+import (
+ "github.com/stretchr/testify/mock"
+ "rsm/models"
+)
+
+type RsmReaderMock struct {
+ mock.Mock
+}
+
+func (m *RsmReaderMock) GetRsmRanInfo(inventoryName string) (*models.RsmRanInfo, error) {
+ args := m.Called(inventoryName)
+ return args.Get(0).(*models.RsmRanInfo), args.Error(1)
+}
+
+func (m *RsmReaderMock) GetRsmGeneralConfiguration() (*models.RsmGeneralConfiguration, error) {
+ args := m.Called()
+ return args.Get(0).(*models.RsmGeneralConfiguration), args.Error(1)
+}
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
-// Licensed under the Apache License, Version 2.0 (the "License");
+// 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
//
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
-
package mocks
import (
"github.com/stretchr/testify/mock"
+ "rsm/models"
)
-type Asn1PduUnpackerMock struct {
+type RsmWriterMock struct {
mock.Mock
}
-func (m *Asn1PduUnpackerMock)UnpackX2apPduAsString(packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (string, error){
- args := m.Called(packedBufferSize, packedBuf, maxMessageBufferSize)
- return args.Get(0).(string), args.Error(1)
+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)
+}
return a.Bool(0), a.Error(1)
}
-func (m *MockSdlInstance) AddMember(group string, member ...interface{}) error{
+func (m *MockSdlInstance) AddMember(group string, member ...interface{}) error {
a := m.Called(group, member)
return a.Error(0)
}
a := m.Called(group)
return a.Get(0).([]string), a.Error(1)
}
-func (m *MockSdlInstance) IsMember(group string, member interface{}) (bool, error){
+func (m *MockSdlInstance) IsMember(group string, member interface{}) (bool, error) {
a := m.Called(group, member)
return a.Bool(0), a.Error(1)
}
-func (m *MockSdlInstance) GroupSize(group string) (int64, error){
- a := m.Called(group,)
+func (m *MockSdlInstance) GroupSize(group string) (int64, error) {
+ a := m.Called(group)
return int64(a.Int(0)), a.Error(1)
}
package models
type Request interface {
-
}
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 models
import (
- "rsm/enums"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "rsm/enums"
)
type ResourceStatusPayload struct {
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 models
+
+type ResourceStatusRequest struct {
+ EnableResourceStatus bool `json:"enableResourceStatus"`
+}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 models
+
+import (
+ "fmt"
+ "strings"
+)
+
+type MeasurementFailureCause struct {
+ MeasurementFailedReportCharacteristics []byte
+}
+
+func (r MeasurementFailureCause) String() string {
+ return fmt.Sprintf("MeasurementFailedReportCharacteristics: %x", r.MeasurementFailedReportCharacteristics)
+}
+
+type MeasurementInitiationResult struct {
+ CellId string
+ MeasurementFailureCauses []*MeasurementFailureCause
+}
+
+func (r MeasurementInitiationResult) String() string {
+ var strBuilder strings.Builder
+ strBuilder.WriteString("[ ")
+ for _, cause := range r.MeasurementFailureCauses {
+ strBuilder.WriteString(cause.String())
+ strBuilder.WriteString(" ")
+ }
+ strBuilder.WriteString(" ]")
+ return fmt.Sprintf("CellId: %s, MeasurementFailureCauses: %s", r.CellId, strBuilder.String())
+}
+
+type ResourceStatusResponse struct {
+ ENB1_Measurement_ID int64
+ ENB2_Measurement_ID int64
+ MeasurementInitiationResults []*MeasurementInitiationResult
+}
+
+func (r ResourceStatusResponse) String() string {
+ var strBuilder strings.Builder
+ strBuilder.WriteString("[ ")
+ for _, result := range r.MeasurementInitiationResults {
+ strBuilder.WriteString(result.String())
+ strBuilder.WriteString(" ")
+ }
+ strBuilder.WriteString(" ]")
+ return fmt.Sprintf("ENB1_Measurement_ID: %d, ENB2_Measurement_ID: %d, MeasurementInitiationResults:%s", r.ENB1_Measurement_ID, r.ENB2_Measurement_ID, strBuilder.String())
+}
type IResponse interface {
Marshal() (string, error)
-}
\ No newline at end of file
+}
func (response RmrMessage) GetMessageAsBytes(logger *logger.Logger) []byte {
return response.Payload
-}
\ No newline at end of file
+}
import "time"
type RmrRequest struct {
- RanName string
- Len int
- Payload []byte
- StartTime time.Time
+ RanName string
+ Len int
+ Payload []byte
+ StartTime time.Time
}
func NewRmrRequest(ranName string, payload []byte, startTime time.Time) *RmrRequest {
payload,
startTime,
}
-}
\ No newline at end of file
+}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 models
+
+import "rsm/enums"
+
+type RsmGeneralConfiguration struct {
+ EnableResourceStatus bool `json:"enableResourceStatus"`
+ PartialSuccessAllowed bool `json:"partialSuccessAllowed"`
+ PrbPeriodic bool `json:"prbPeriodic"`
+ TnlLoadIndPeriodic bool `json:"tnlLoadIndPeriodic"`
+ HwLoadIndPeriodic bool `json:"wwLoadIndPeriodic"`
+ AbsStatusPeriodic bool `json:"absStatusPeriodic"`
+ RsrpMeasurementPeriodic bool `json:"rsrpMeasurementPeriodic"`
+ CsiPeriodic bool `json:"csiPeriodic"`
+ PeriodicityMs enums.ReportingPeriodicity `json:"periodicityMs"`
+ PeriodicityRsrpMeasurementMs enums.ReportingPeriodicityRSRPMR `json:"periodicityRsrpMeasurementMs"`
+ PeriodicityCsiMs enums.ReportingPeriodicityCSIR `json:"periodicityCsiMs"`
+}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 models
+
+import (
+ "rsm/enums"
+)
+
+type RsmRanInfo struct {
+ RanName string `json:"ranName"`
+ Enb1MeasurementId int64 `json:"enb1MeasurementId"`
+ Enb2MeasurementId int64 `json:"enb2MeasurementId"`
+ Action enums.RsmAction `json:"action"`
+ ActionStatus bool `json:"actionStatus"`
+}
+
+func NewRsmRanInfo(ranName string, enb1MeasurementId int64, enb2MeasurementId int64, action enums.RsmAction, actionStatus bool) *RsmRanInfo {
+ return &RsmRanInfo{
+ RanName: ranName,
+ Enb1MeasurementId: enb1MeasurementId,
+ Enb2MeasurementId: enb2MeasurementId,
+ Action: action,
+ ActionStatus: actionStatus,
+ }
+}
package httpmsghandlerprovider
import (
- "rsm/configuration"
"rsm/handlers/httpmsghandlers"
"rsm/logger"
"rsm/rsmerrors"
"rsm/services"
- "rsm/services/rmrsender"
)
type IncomingRequest string
const (
- ResourceStatusInitiation = "ResourceStatusInitiation"
+ ResourceStatusRequest = "ResourceStatusRequest"
)
type RequestHandlerProvider struct {
- requestMap map[IncomingRequest]*httpmsghandlers.RequestHandler
+ requestMap map[IncomingRequest]httpmsghandlers.RequestHandler
logger *logger.Logger
}
-func NewRequestHandlerProvider(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService) *RequestHandlerProvider {
+func NewRequestHandlerProvider(logger *logger.Logger, rNibDataService services.RNibDataService, resourceStatusService services.IResourceStatusService) *RequestHandlerProvider {
return &RequestHandlerProvider{
- requestMap: initRequestHandlerMap(logger, rmrSender, config, rNibDataService),
+ requestMap: initRequestHandlerMap(logger, rNibDataService, resourceStatusService),
logger: logger,
}
}
-func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService) map[IncomingRequest]*httpmsghandlers.RequestHandler {
+func initRequestHandlerMap(logger *logger.Logger, rNibDataService services.RNibDataService, resourceStatusService services.IResourceStatusService) map[IncomingRequest]httpmsghandlers.RequestHandler {
- return map[IncomingRequest]*httpmsghandlers.RequestHandler{
+ return map[IncomingRequest]httpmsghandlers.RequestHandler{
+ ResourceStatusRequest: httpmsghandlers.NewResourceStatusRequestHandler(logger, rNibDataService, resourceStatusService),
}
}
-func (provider RequestHandlerProvider) GetHandler(requestType IncomingRequest) (*httpmsghandlers.RequestHandler, error) {
+func (provider RequestHandlerProvider) GetHandler(requestType IncomingRequest) (httpmsghandlers.RequestHandler, error) {
handler, ok := provider.requestMap[requestType]
if !ok {
}
return handler, nil
-}
+}
\ No newline at end of file
"github.com/stretchr/testify/assert"
"reflect"
"rsm/configuration"
+ "rsm/handlers/httpmsghandlers"
+ "rsm/logger"
+ "rsm/mocks"
"rsm/rsmerrors"
- "rsm/tests/testhelper"
+ "rsm/services"
"testing"
)
func setupTest(t *testing.T) *RequestHandlerProvider {
+ log, err := logger.InitLogger(logger.DebugLevel)
+ if err != nil {
+ t.Errorf("#... - failed to initialize logger, error: %s", err)
+ }
+
config, err := configuration.ParseConfiguration()
if err != nil {
t.Errorf("#... - failed to parse configuration error: %s", err)
}
- rnibDataService, rmrSender, log := testhelper.InitTestCase(t)
- return NewRequestHandlerProvider(log, rmrSender, config, rnibDataService)
+
+ resourceStatusServiceMock := &mocks.ResourceStatusServiceMock{}
+ rnibReaderMock := &mocks.RnibReaderMock{}
+ rsmReaderMock := &mocks.RsmReaderMock{}
+ rsmWriterMock := &mocks.RsmWriterMock{}
+
+ rnibDataService := services.NewRnibDataService(log, config, rnibReaderMock, rsmReaderMock, rsmWriterMock)
+ return NewRequestHandlerProvider(log, rnibDataService, resourceStatusServiceMock)
}
func TestNewRequestHandlerProvider(t *testing.T) {
assert.NotNil(t, provider)
}
+func TestResourceStatusRequestHandler(t *testing.T) {
+ provider := setupTest(t)
+ handler, err := provider.GetHandler(ResourceStatusRequest)
+
+ assert.NotNil(t, provider)
+ assert.Nil(t, err)
+
+ _, ok := handler.(*httpmsghandlers.ResourceStatusRequestHandler)
+
+ assert.True(t, ok)
+}
+
func TestNewRequestHandlerProvider_InternalError(t *testing.T) {
provider := setupTest(t)
"rsm/converters"
"rsm/handlers/rmrmsghandlers"
"rsm/logger"
- "rsm/managers"
"rsm/rmrcgo"
"rsm/services"
"rsm/services/rmrsender"
msgHandlers map[int]rmrmsghandlers.RmrMessageHandler
}
-func NewMessageHandlerProvider(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, resourceStatusInitiateManager *managers.ResourceStatusInitiateManager, unpacker converters.Asn1PduUnpacker) *MessageHandlerProvider {
+func NewMessageHandlerProvider(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, resourceStatusService *services.ResourceStatusService, rsConverter converters.ResourceStatusResponseConverter, rsFailureConverter converters.ResourceStatusFailureConverter) *MessageHandlerProvider {
return &MessageHandlerProvider{
- msgHandlers: initMessageHandlersMap(logger, config, rnibDataService, rmrSender, resourceStatusInitiateManager, unpacker),
+ msgHandlers: initMessageHandlersMap(logger, config, rnibDataService, rmrSender, resourceStatusService, rsConverter, rsFailureConverter),
}
}
-func initMessageHandlersMap(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, resourceStatusInitiateManager *managers.ResourceStatusInitiateManager, unpacker converters.Asn1PduUnpacker) map[int]rmrmsghandlers.RmrMessageHandler {
+func initMessageHandlersMap(logger *logger.Logger, config *configuration.Configuration, rnibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender, resourceStatusService *services.ResourceStatusService, rsConverter converters.ResourceStatusResponseConverter, rsFailureConverter converters.ResourceStatusFailureConverter) map[int]rmrmsghandlers.RmrMessageHandler {
return map[int]rmrmsghandlers.RmrMessageHandler{
- rmrcgo.RanConnected: rmrmsghandlers.NewResourceStatusInitiateNotificationHandler(logger, config, resourceStatusInitiateManager, RanConnected),
- rmrcgo.RanRestarted: rmrmsghandlers.NewResourceStatusInitiateNotificationHandler(logger, config, resourceStatusInitiateManager, RanRestarted),
- rmrcgo.RicResStatusFailure: rmrmsghandlers.NewResourceStatusFailureHandler(logger, unpacker),
- rmrcgo.RicResStatusResp: rmrmsghandlers.NewResourceStatusResponseHandler(logger),
+ rmrcgo.RanConnected: rmrmsghandlers.NewResourceStatusInitiateNotificationHandler(logger, rnibDataService, resourceStatusService, RanConnected),
+ rmrcgo.RanRestarted: rmrmsghandlers.NewResourceStatusInitiateNotificationHandler(logger, rnibDataService, resourceStatusService, RanRestarted),
+ rmrcgo.RicResStatusFailure: rmrmsghandlers.NewResourceStatusFailureHandler(logger, rsFailureConverter),
+ rmrcgo.RicResStatusResp: rmrmsghandlers.NewResourceStatusResponseHandler(logger, rsConverter, rnibDataService),
}
}
handler, ok := provider.msgHandlers[messageType]
if !ok {
- msg := fmt.Sprintf("#MessageHandlerProvider.GetMessageHandler - notification handler not found for message %d",messageType )
+ msg := fmt.Sprintf("#MessageHandlerProvider.GetMessageHandler - notification handler not found for message %d", messageType)
return nil, errors.New(msg)
}
import (
"fmt"
"rsm/configuration"
+ "rsm/converters"
+ "rsm/e2pdus"
"rsm/handlers/rmrmsghandlers"
- "rsm/managers"
+ "rsm/services"
"rsm/tests/testhelper"
"strings"
"testing"
if err != nil {
t.Errorf("#... - failed to parse configuration error: %s", err)
}
- resourceStatusInitiateManager := managers.NewResourceStatusInitiateManager(logger, rnibDataService, rmrSender)
-
+ resourceStatusService := services.NewResourceStatusService(logger, rmrSender)
+ unpacker := converters.NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
var testCases = []struct {
msgType int
handler rmrmsghandlers.RmrMessageHandler
}{
- {rmrcgo.RanConnected, rmrmsghandlers.NewResourceStatusInitiateNotificationHandler(logger, config, resourceStatusInitiateManager, RanConnected)},
- {rmrcgo.RanRestarted, rmrmsghandlers.NewResourceStatusInitiateNotificationHandler(logger, config, resourceStatusInitiateManager, RanRestarted)},
+ {rmrcgo.RanConnected, rmrmsghandlers.NewResourceStatusInitiateNotificationHandler(logger, rnibDataService, resourceStatusService, RanConnected)},
+ {rmrcgo.RanRestarted, rmrmsghandlers.NewResourceStatusInitiateNotificationHandler(logger, rnibDataService, resourceStatusService, RanRestarted)},
}
for _, tc := range testCases {
- provider := NewMessageHandlerProvider(logger, config, rnibDataService, rmrSender, resourceStatusInitiateManager, nil)
+ provider := NewMessageHandlerProvider(logger, config, rnibDataService, rmrSender, resourceStatusService, converters.NewResourceStatusResponseConverter(unpacker), converters.NewResourceStatusFailureConverter(unpacker))
t.Run(fmt.Sprintf("%d", tc.msgType), func(t *testing.T) {
handler, err := provider.GetMessageHandler(tc.msgType)
if err != nil {
if err != nil {
t.Errorf("#... - failed to parse configuration error: %s", err)
}
- resourceStatusInitiateManager := managers.NewResourceStatusInitiateManager(logger, rnibDataService, rmrSender)
+ resourceStatusService := services.NewResourceStatusService(logger, rmrSender)
+ unpacker := converters.NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
var testCases = []struct {
msgType int
{9999 /*unknown*/, "notification handler not found"},
}
for _, tc := range testCases {
- provider := NewMessageHandlerProvider(logger, config, rnibDataService, rmrSender, resourceStatusInitiateManager, nil)
+ provider := NewMessageHandlerProvider(logger, config, rnibDataService, rmrSender, resourceStatusService, converters.NewResourceStatusResponseConverter(unpacker), converters.NewResourceStatusFailureConverter(unpacker))
t.Run(fmt.Sprintf("%d", tc.msgType), func(t *testing.T) {
_, err := provider.GetMessageHandler(tc.msgType)
if err == nil {
readyIntervalSec: 1
rnib:
maxRnibConnectionAttempts: 3
- rnibRetryIntervalMs: 10
-resourceStatusParams:
- enableResourceStatus: true
- partialSuccessAllowed: true
- prbPeriodic: true
- tnlLoadIndPeriodic: true
- hwLoadIndPeriodic: true
- absStatusPeriodic: true
- rsrpMeasurementPeriodic: true
- csiPeriodic: true
- periodicityMs: 1000
- periodicityRsrpMeasurementMs: 480
- periodicityCsiMs: 20
+ rnibRetryIntervalMs: 10
\ No newline at end of file
"rsm/tests"
"strconv"
"testing"
- "time"
)
var (
assert.Equal(t, msg.Meid, "RanName")
assert.Equal(t, msg.Len, len(tests.DummyPayload))
}
-//TODO check why test failure and TestIsReadySuccess success
-func TestInitFailure(t *testing.T) {
- log := initLog(t)
- go initRmr(tests.ReadyIntervalSec, tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
- time.Sleep(time.Second)
- if msgr != nil {
- t.Errorf("The rmr router is ready, should be not ready")
- }
-}
-
-func TestIsReadyFailure(t *testing.T) {
- log := initLog(t)
- go initRmr(tests.ReadyIntervalSec, tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
- assert.True(t, msgr == nil || !msgr.IsReady())
-}
func TestSendRecvMsgSuccess(t *testing.T) {
log := initLog(t)
- go initRmr(tests.ReadyIntervalSec, tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
- time.Sleep(time.Duration(2) * time.Second)
- if msgr == nil || !msgr.IsReady() {
+ initRmr(tests.ReadyIntervalSec, tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
+ if msgr == nil || !msgr.IsReady() {
t.Errorf("#rmr_c_go_api_test.TestSendRecvMsgSuccess - The rmr router is not ready")
}
func TestSendMsgRmrInvalidPortError(t *testing.T) {
log := initLog(t)
- go initRmr(tests.ReadyIntervalSec, "tcp:" + strconv.Itoa(5555), tests.MaxMsgSize, tests.Flags, log)
- time.Sleep(time.Duration(2) * time.Second)
- if msgr == nil || !msgr.IsReady() {
+ initRmr(tests.ReadyIntervalSec, "tcp:"+strconv.Itoa(5555), tests.MaxMsgSize, tests.Flags, log)
+ if msgr == nil || !msgr.IsReady() {
t.Errorf("#rmr_c_go_api_test.TestSendMsgRmrInvalidPortError - The rmr router is not ready")
}
func TestSendMsgRmrInvalidMsgNumError(t *testing.T) {
log := initLog(t)
- go initRmr(tests.ReadyIntervalSec, tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
- time.Sleep(time.Duration(2) * time.Second)
- if msgr == nil || !msgr.IsReady() {
+ initRmr(tests.ReadyIntervalSec, tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
+ if msgr == nil || !msgr.IsReady() {
t.Errorf("#rmr_c_go_api_test.TestSendMsgRmrInvalidMsgNumError - The rmr router is not ready")
}
func TestIsReadySuccess(t *testing.T) {
log := initLog(t)
- go initRmr(tests.ReadyIntervalSec, tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
- time.Sleep(time.Duration(tests.ReadyIntervalSec))
- if msgr == nil || !msgr.IsReady() {
+ initRmr(tests.ReadyIntervalSec, tests.GetPort(), tests.MaxMsgSize, tests.Flags, log)
+ if msgr == nil || !msgr.IsReady() {
t.Errorf("#rmr_c_go_api_test.TestIsReadySuccess - The rmr router is not ready")
}
+
+ msgr.Close()
}
-func initRmr(readyIntervalSec int, port string, maxMsgSize int, flags int, log *logger.Logger){
+func initRmr(readyIntervalSec int, port string, maxMsgSize int, flags int, log *logger.Logger) {
var ctx *Context
msgr = ctx.Init(readyIntervalSec, port, maxMsgSize, flags, log)
}
t.Errorf("#rmr_c_go_api_test.initLog - failed to initialize logger, error: %s", err)
}
return log
-}
\ No newline at end of file
+}
)
func convertToMBuf(m *C.rmr_mbuf_t) *MBuf {
- payloadArr := C.GoBytes(unsafe.Pointer(m.payload),C.int(m.len))
- xActionArr := C.GoBytes(unsafe.Pointer(m.xaction),C.int(RMR_MAX_XACTION_LEN))
+ payloadArr := C.GoBytes(unsafe.Pointer(m.payload), C.int(m.len))
+ xActionArr := C.GoBytes(unsafe.Pointer(m.xaction), C.int(RMR_MAX_XACTION_LEN))
// Trim padding (space and 0)
- xActionStr := strings.TrimRight(string(xActionArr),"\040\000")
+ xActionStr := strings.TrimRight(string(xActionArr), "\040\000")
xActionArr = []byte(xActionStr)
mbuf := &MBuf{
- MType: int(m.mtype),
- Len: int(m.len),
+ MType: int(m.mtype),
+ Len: int(m.len),
Payload: &payloadArr,
XAction: &xActionArr,
}
meidBuf := make([]byte, RMR_MAX_MEID_LEN)
if meidCstr := C.rmr_get_meid(m, (*C.uchar)(unsafe.Pointer(&meidBuf[0]))); meidCstr != nil {
- mbuf.Meid = strings.TrimRight(string(meidBuf), "\000")
+ mbuf.Meid = strings.TrimRight(string(meidBuf), "\000")
}
return mbuf
func (ctx *Context) getAllocatedCRmrMBuf(logger *logger.Logger, mBuf *MBuf, maxMsgSize int) (cMBuf *C.rmr_mbuf_t) {
var xActionBuf [RMR_MAX_XACTION_LEN]byte
- var meidBuf[RMR_MAX_MEID_LEN]byte
+ var meidBuf [RMR_MAX_MEID_LEN]byte
cMBuf = C.rmr_alloc_msg(ctx.RmrCtx, C.int(maxMsgSize))
cMBuf.mtype = C.int(mBuf.MType)
//Add padding
copy(xActionBuf[:], *mBuf.XAction)
- for i:= xActionLen; i < RMR_MAX_XACTION_LEN; i++{
+ for i := xActionLen; i < RMR_MAX_XACTION_LEN; i++ {
xActionBuf[i] = '\040' //space
}
// Add padding
copy(meidBuf[:], mBuf.Meid)
- for i:= len(mBuf.Meid); i < RMR_MAX_MEID_LEN; i++{
+ for i := len(mBuf.Meid); i < RMR_MAX_MEID_LEN; i++ {
meidBuf[i] = 0
}
ctx.Logger.Errorf(
"#rmrCgoUtils.getAllocatedCRmrMBuf - Failed to read xAction data to allocated RMR message buffer")
}
- len := C.rmr_bytes2meid(cMBuf, (*C.uchar)(unsafe.Pointer(&meidBuf[0])), C.int(RMR_MAX_MEID_LEN))
+ len := C.rmr_bytes2meid(cMBuf, (*C.uchar)(unsafe.Pointer(&meidBuf[0])), C.int(RMR_MAX_MEID_LEN))
if int(len) != RMR_MAX_MEID_LEN {
ctx.Logger.Errorf(
"#rmrCgoUtils.getAllocatedCRmrMBuf - Failed to copy meid data to allocated RMR message buffer")
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 rsmdb
+
+import (
+ "encoding/json"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+ "reflect"
+ "rsm/models"
+)
+
+type rsmReaderInstance struct {
+ sdl common.ISdlInstance
+}
+
+// RsmReader interface allows retrieving data from redis BD by various keys
+type RsmReader interface {
+ GetRsmGeneralConfiguration() (*models.RsmGeneralConfiguration, error)
+ GetRsmRanInfo(ranName string) (*models.RsmRanInfo, error)
+}
+
+// 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)
+ if err != nil {
+ return nil, err
+ }
+
+ rsmRanInfo := &models.RsmRanInfo{}
+
+ err = r.getByKeyAndUnmarshal(key, rsmRanInfo)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return rsmRanInfo, nil
+}
+
+// GetRsmGeneralConfiguration returns resource status request related configuration
+func (r *rsmReaderInstance) GetRsmGeneralConfiguration() (*models.RsmGeneralConfiguration, error) {
+ 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 {
+ return common.NewInternalError(err)
+ }
+ if data != nil && data[key] != nil {
+ err = json.Unmarshal([]byte(data[key].(string)), entity)
+ if err != nil {
+ return common.NewInternalError(err)
+ }
+ return nil
+ }
+ 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"
+}
--- /dev/null
+/*******************************************************************************
+ *
+ * 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
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 rsmdb
+
+import (
+ "encoding/json"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+ "rsm/models"
+)
+
+type rsmWriterInstance struct {
+ sdl common.ISdlInstance
+}
+
+// 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
+}
+
+// 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)
+
+ if err != nil {
+ return err
+ }
+
+ 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 the Go structure to json and saves it to the DB with key 'key'
+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, key, data)
+
+ err = r.sdl.Set(pairs)
+
+ if err != nil {
+ return common.NewInternalError(err)
+ }
+
+ return nil
+}
--- /dev/null
+/*******************************************************************************
+ *
+ * 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")
+}
package rsmerrors
type BaseError struct {
- Code int
+ Code int
Message string
}
}
func NewHeaderValidationError() *HeaderValidationError {
- return &HeaderValidationError {
+ return &HeaderValidationError{
&BaseError{
- Code: 415,
+ Code: 415,
Message: "Header validation error",
},
}
}
func NewInternalError() *InternalError {
- return &InternalError {
+ return &InternalError{
&BaseError{
- Code: 501,
+ Code: 501,
Message: "Internal Server Error. Please try again later",
},
}
package rsmerrors
-
type InvalidJsonError struct {
*BaseError
}
func (e *InvalidJsonError) Error() string {
return e.Message
}
-
}
func NewRnibDbError() *RnibDbError {
- return &RnibDbError {
+ return &RnibDbError{
&BaseError{
- Code: 500,
+ Code: 500,
Message: "RNIB error",
},
}
func (e *RnibDbError) Error() string {
return e.Message
-}
\ No newline at end of file
+}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 rsmerrors
+
+import "fmt"
+
+type RsmError struct {
+ *BaseError
+}
+
+func NewRsmError(numberOfFails int) *RsmError {
+ return &RsmError{
+ &BaseError{
+ Code: 503,
+ Message: fmt.Sprintf("Did not send %d resource status requests to RMR.", numberOfFails),
+ },
+ }
+}
+
+func (e *RsmError) Error() string {
+ return e.Message
+}
return &WrongStateError{
&BaseError{
Code: 403,
- Message: fmt.Sprintf("Activity %s rejected. RAN current state %s does not allow its execution ", activityName, state) ,
+ Message: fmt.Sprintf("Activity %s rejected. RAN current state %s does not allow its execution ", activityName, state),
},
}
}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 services
+
+import (
+ "fmt"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "rsm/e2pdus"
+ "rsm/enums"
+ "rsm/logger"
+ "rsm/models"
+ "rsm/rmrcgo"
+ "rsm/services/rmrsender"
+)
+
+type ResourceStatusService struct {
+ logger *logger.Logger
+ rmrSender *rmrsender.RmrSender
+}
+
+type IResourceStatusService interface {
+ BuildAndSendInitiateRequest(nodeb *entities.NodebInfo, config *models.RsmGeneralConfiguration, enb1MeasurementId int64) error
+ BuildAndSendStopRequest(nodeb *entities.NodebInfo, config *models.RsmGeneralConfiguration, enb1MeasurementId int64, enb2MeasurementId int64) error
+}
+
+func NewResourceStatusService(logger *logger.Logger, rmrSender *rmrsender.RmrSender) *ResourceStatusService {
+ return &ResourceStatusService{
+ logger: logger,
+ rmrSender: rmrSender,
+ }
+}
+
+func (m *ResourceStatusService) BuildAndSendInitiateRequest(nodeb *entities.NodebInfo, config *models.RsmGeneralConfiguration, enb1MeasurementId int64) error {
+
+ return m.buildAndSendResourceStatusRequest(enums.Registration_Request_start, nodeb, config, enb1MeasurementId, 0)
+}
+
+func (m *ResourceStatusService) BuildAndSendStopRequest(nodeb *entities.NodebInfo, config *models.RsmGeneralConfiguration, enb1MeasurementId int64, enb2MeasurementId int64) error {
+
+ return m.buildAndSendResourceStatusRequest(enums.Registration_Request_stop, nodeb, config, enb1MeasurementId, enb2MeasurementId)
+}
+
+func (m *ResourceStatusService) buildAndSendResourceStatusRequest(registrationRequest enums.Registration_Request, nodeb *entities.NodebInfo, config *models.RsmGeneralConfiguration, enb1MeasurementId int64, enb2MeasurementId int64) error {
+
+ cellIdList, err := m.extractCellIdList(nodeb)
+
+ if err != nil {
+ return err
+ }
+
+ requestParams := buildResourceStatusRequestParams(config, cellIdList, enb1MeasurementId, enb2MeasurementId)
+
+ payload, payloadAsString, err := e2pdus.BuildPackedResourceStatusRequest(registrationRequest, requestParams, e2pdus.MaxAsn1PackedBufferSize, e2pdus.MaxAsn1CodecMessageBufferSize, m.logger.DebugEnabled())
+
+ if err != nil {
+ m.logger.Errorf("#ResourceStatusService.buildAndSendResourceStatusRequest - RAN name: %s. Failed to build and pack resource status %s request. error: %s", nodeb.RanName, registrationRequest, err)
+ return err
+ }
+
+ m.logger.Debugf("#ResourceStatusService.buildAndSendResourceStatusRequest - RAN name: %s. Successfully build packed payload: %s", nodeb.RanName, payloadAsString)
+ rmrMsg := models.NewRmrMessage(rmrcgo.RicResStatusReq, nodeb.RanName, payload)
+
+ return m.rmrSender.Send(rmrMsg)
+}
+
+func (m *ResourceStatusService) extractCellIdList(nodeb *entities.NodebInfo) ([]string, error) {
+
+ enb, ok := nodeb.Configuration.(*entities.NodebInfo_Enb)
+
+ if !ok {
+ m.logger.Errorf("#ResourceStatusService.extractCellIdList - RAN name: %s - invalid configuration", nodeb.RanName)
+ return []string{}, fmt.Errorf("invalid configuration for RAN %s", nodeb.RanName)
+ }
+
+ cells := enb.Enb.ServedCells
+
+ if len(cells) == 0 {
+ m.logger.Errorf("#ResourceStatusService.extractCellIdList - RAN name: %s - empty cell list", nodeb.RanName)
+ return []string{}, fmt.Errorf("empty cell list for RAN %s", nodeb.RanName)
+ }
+
+ cellIdList := make([]string, len(cells))
+ for index, cellInfo := range cells {
+ cellIdList[index] = cellInfo.CellId
+ }
+
+ return cellIdList, nil
+}
+
+func buildResourceStatusRequestParams(config *models.RsmGeneralConfiguration, cellIdList []string, enb1MeasurementId int64, enb2MeasurementId int64) *e2pdus.ResourceStatusRequestData {
+ return &e2pdus.ResourceStatusRequestData{
+ CellIdList: cellIdList,
+ MeasurementID: e2pdus.Measurement_ID(enb1MeasurementId),
+ MeasurementID2: e2pdus.Measurement_ID(enb2MeasurementId),
+ PartialSuccessAllowed: config.PartialSuccessAllowed,
+ PrbPeriodic: config.PrbPeriodic,
+ TnlLoadIndPeriodic: config.TnlLoadIndPeriodic,
+ HwLoadIndPeriodic: config.HwLoadIndPeriodic,
+ AbsStatusPeriodic: config.AbsStatusPeriodic,
+ RsrpMeasurementPeriodic: config.RsrpMeasurementPeriodic,
+ CsiPeriodic: config.CsiPeriodic,
+ PeriodicityMS: config.PeriodicityMs,
+ PeriodicityRsrpMeasurementMS: config.PeriodicityRsrpMeasurementMs,
+ PeriodicityCsiMS: config.PeriodicityCsiMs,
+ }
+}
--- /dev/null
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 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 services
+
+import (
+ "fmt"
+ "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+ "github.com/stretchr/testify/assert"
+ "rsm/enums"
+ "rsm/logger"
+ "rsm/mocks"
+ "rsm/models"
+ "rsm/rmrcgo"
+ "rsm/rsmerrors"
+ "rsm/services/rmrsender"
+ "rsm/tests"
+ "testing"
+)
+
+const RanName = "test"
+const NodebOneCellPackedExample = "0009003c00000800270003000000001c00010000260004fe000000001d400d00001f40080002f8290007ab00001e4001000040400100006d4001400091400120"
+const NodebTwoCellsPackedExample = "0009004800000800270003000000001c00010000260004fe000000001d401901001f40080002f8290007ab00001f40080002f8290007ab50001e4001000040400100006d4001400091400120"
+const StopPackedExample = "0009004f0000090027000300000000280003000001001c00014000260004fe000000001d401901001f40080002f8290007ab00001f40080002f8290007ab50001e4001000040400100006d4001400091400120"
+
+func initResourceStatusServiceTest(t *testing.T) (*mocks.RmrMessengerMock, *models.RsmGeneralConfiguration, *ResourceStatusService) {
+ logger, err := logger.InitLogger(logger.DebugLevel)
+ if err != nil {
+ t.Errorf("#... - failed to initialize logger, error: %s", err)
+ }
+
+ rmrMessengerMock := &mocks.RmrMessengerMock{}
+ rmrSender := InitRmrSender(rmrMessengerMock, logger)
+ resourceStatusService := NewResourceStatusService(logger, rmrSender)
+
+ rsmGeneralConfiguration := 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,
+ }
+
+ return rmrMessengerMock, &rsmGeneralConfiguration, resourceStatusService
+}
+
+func TestOneCellSuccess(t *testing.T) {
+ cellId := "02f829:0007ab00"
+ rmrMessengerMock, rsmGeneralConfiguration, resourceStatusService := initResourceStatusServiceTest(t)
+
+ xaction := []byte(RanName)
+ nodebInfo := &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ Configuration: &entities.NodebInfo_Enb{
+ Enb: &entities.Enb{
+ ServedCells: []*entities.ServedCellInfo{{CellId: cellId}},
+ },
+ },
+ }
+
+ var expectedPayload []byte
+ _, _ = fmt.Sscanf(NodebOneCellPackedExample, "%x", &expectedPayload)
+ var err error
+ expectedMbuf := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload), RanName, &expectedPayload, &xaction)
+ rmrMessengerMock.On("SendMsg", expectedMbuf).Return(&rmrcgo.MBuf{}, err)
+ err = resourceStatusService.BuildAndSendInitiateRequest(nodebInfo, rsmGeneralConfiguration, enums.Enb1MeasurementId)
+ assert.Nil(t, err)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf)
+}
+
+func TestTwoCellsSuccess(t *testing.T) {
+ cellId1 := "02f829:0007ab00"
+ cellId2 := "02f829:0007ab50"
+ rmrMessengerMock, rsmGeneralConfiguration, resourceStatusService := initResourceStatusServiceTest(t)
+ xaction := []byte(RanName)
+ nodebInfo := &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ Configuration: &entities.NodebInfo_Enb{
+ Enb: &entities.Enb{
+ ServedCells: []*entities.ServedCellInfo{{CellId: cellId1}, {CellId: cellId2}},
+ },
+ },
+ }
+
+ var expectedPayload []byte
+ _, _ = fmt.Sscanf(NodebTwoCellsPackedExample, "%x", &expectedPayload)
+ expectedMbuf := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload), RanName, &expectedPayload, &xaction)
+ var err error
+ rmrMessengerMock.On("SendMsg", expectedMbuf).Return(&rmrcgo.MBuf{}, err)
+ err = resourceStatusService.BuildAndSendInitiateRequest(nodebInfo, rsmGeneralConfiguration, enums.Enb1MeasurementId)
+ assert.Nil(t, err)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf)
+}
+
+func TestOneCellSendFailure(t *testing.T) {
+ cellId := "02f829:0007ab00"
+ rmrMessengerMock, rsmGeneralConfiguration, resourceStatusService := initResourceStatusServiceTest(t)
+
+ xaction := []byte(RanName)
+ var err error
+ nodebInfo := &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ Configuration: &entities.NodebInfo_Enb{
+ Enb: &entities.Enb{
+ ServedCells: []*entities.ServedCellInfo{{CellId: cellId}},
+ },
+ },
+ }
+
+ var expectedPayload []byte
+ _, _ = fmt.Sscanf(NodebOneCellPackedExample, "%x", &expectedPayload)
+ expectedMbuf := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload), RanName, &expectedPayload, &xaction)
+ rmrMessengerMock.On("SendMsg", expectedMbuf).Return(&rmrcgo.MBuf{}, rsmerrors.NewRmrError())
+ err = resourceStatusService.BuildAndSendInitiateRequest(nodebInfo, rsmGeneralConfiguration, 1)
+ assert.NotNil(t, err)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf)
+}
+
+
+
+func TestNodebConfigurationFailure(t *testing.T) {
+ rmrMessengerMock, rsmGeneralConfiguration, resourceStatusService := initResourceStatusServiceTest(t)
+ nodebInfo := &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ }
+
+ err := resourceStatusService.BuildAndSendInitiateRequest(nodebInfo, rsmGeneralConfiguration, enums.Enb1MeasurementId)
+ assert.NotNil(t, err)
+ rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
+
+func TestNodebEmptyCellList(t *testing.T) {
+ rmrMessengerMock, rsmGeneralConfiguration, resourceStatusService := initResourceStatusServiceTest(t)
+ nodebInfo := &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ Configuration: &entities.NodebInfo_Enb{
+ Enb: &entities.Enb{
+ ServedCells: []*entities.ServedCellInfo{},
+ },
+ },
+ }
+
+ err := resourceStatusService.BuildAndSendInitiateRequest(nodebInfo, rsmGeneralConfiguration, enums.Enb1MeasurementId)
+ assert.NotNil(t, err)
+ rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
+
+func TestPackFailure(t *testing.T) {
+ rmrMessengerMock, rsmGeneralConfiguration, resourceStatusService := initResourceStatusServiceTest(t)
+ nodebInfo := &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ Configuration: &entities.NodebInfo_Enb{
+ Enb: &entities.Enb{
+ ServedCells: []*entities.ServedCellInfo{{CellId: ""}},
+ },
+ },
+ }
+
+ err := resourceStatusService.BuildAndSendInitiateRequest(nodebInfo, rsmGeneralConfiguration, enums.Enb1MeasurementId)
+ assert.NotNil(t, err)
+ rmrMessengerMock.AssertNotCalled(t, "SendMsg")
+}
+
+func TestBuildAndSendStopRequestSuccess(t *testing.T) {
+ rmrMessengerMock, rsmGeneralConfiguration, resourceStatusService := initResourceStatusServiceTest(t)
+
+ cellId1 := "02f829:0007ab00"
+ cellId2 := "02f829:0007ab50"
+ nodebInfo := &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ Configuration: &entities.NodebInfo_Enb{
+ Enb: &entities.Enb{
+ ServedCells: []*entities.ServedCellInfo{{CellId: cellId1}, {CellId: cellId2}},
+ },
+ },
+ }
+ xaction := []byte(RanName)
+ var expectedPayload []byte
+ _, _ = fmt.Sscanf(StopPackedExample, "%x", &expectedPayload)
+ expectedMbuf := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload), RanName, &expectedPayload, &xaction)
+ var err error
+ rmrMessengerMock.On("SendMsg", expectedMbuf).Return(&rmrcgo.MBuf{}, err)
+ err = resourceStatusService.BuildAndSendStopRequest(nodebInfo, rsmGeneralConfiguration, enums.Enb1MeasurementId, 2)
+ assert.Nil(t, err)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf)
+}
+
+func TestBuildAndSendStopRequestSendFailure(t *testing.T) {
+ rmrMessengerMock, rsmGeneralConfiguration, resourceStatusService := initResourceStatusServiceTest(t)
+
+ xaction := []byte(RanName)
+ cellId1 := "02f829:0007ab00"
+ cellId2 := "02f829:0007ab50"
+ nodebInfo := &entities.NodebInfo{
+ RanName: RanName,
+ ConnectionStatus: entities.ConnectionStatus_CONNECTED,
+ Configuration: &entities.NodebInfo_Enb{
+ Enb: &entities.Enb{
+ ServedCells: []*entities.ServedCellInfo{{CellId: cellId1}, {CellId: cellId2}},
+ },
+ },
+ }
+
+ var err error
+ var expectedPayload []byte
+ _, _ = fmt.Sscanf(StopPackedExample, "%x", &expectedPayload)
+ expectedMbuf := rmrcgo.NewMBuf(rmrcgo.RicResStatusReq, len(expectedPayload), RanName, &expectedPayload, &xaction)
+ rmrMessengerMock.On("SendMsg", expectedMbuf).Return(&rmrcgo.MBuf{}, rsmerrors.NewRmrError())
+ err = resourceStatusService.BuildAndSendStopRequest(nodebInfo, rsmGeneralConfiguration, enums.Enb1MeasurementId, 2)
+
+ assert.NotNil(t, err)
+ rmrMessengerMock.AssertCalled(t, "SendMsg", expectedMbuf)
+}
+
+func InitRmrSender(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *rmrsender.RmrSender {
+ rmrMessenger := rmrcgo.RmrMessenger(rmrMessengerMock)
+ rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger)
+ return rmrsender.NewRmrSender(log, rmrMessenger)
+}
// TODO: go routine?
r.nManager.HandleMessage(mbuf)
}
-}
\ No newline at end of file
+}
import (
"fmt"
"rsm/configuration"
+ "rsm/converters"
+ "rsm/e2pdus"
"rsm/logger"
- "rsm/managers"
"rsm/managers/rmrmanagers"
"rsm/mocks"
"rsm/rmrcgo"
+ "rsm/services"
"rsm/tests"
"rsm/tests/testhelper"
"testing"
if err != nil {
t.Errorf("#... - failed to parse configuration error: %s", err)
}
- resourceStatusInitiateManager := managers.NewResourceStatusInitiateManager(logger, rnibDataService, rmrSender)
+ resourceStatusService := services.NewResourceStatusService(logger, rmrSender)
rmrMessenger := initRmrMessenger(logger)
- manager := rmrmanagers.NewRmrMessageManager(logger, config, rnibDataService, rmrSender, resourceStatusInitiateManager, nil)
+ unpacker := converters.NewX2apPduUnpacker(logger, e2pdus.MaxAsn1CodecMessageBufferSize)
+ manager := rmrmanagers.NewRmrMessageManager(logger, config, rnibDataService, rmrSender, resourceStatusService, converters.NewResourceStatusResponseConverter(unpacker), converters.NewResourceStatusFailureConverter(unpacker))
return NewRmrReceiver(logger, rmrMessenger, manager)
}
r.logger.Infof("#RmrSender.Send - RAN name: %s , Message type: %d - Successfully sent RMR message", rmrMessage.RanName, rmrMessage.MsgType)
return nil
-}
\ No newline at end of file
+}
t.Errorf("#tests.initLog - failed to initialize logger, error: %s", err)
}
return log
-}
\ No newline at end of file
+}
"net"
"rsm/configuration"
"rsm/logger"
+ "rsm/models"
+ "rsm/rsmdb"
"time"
)
type RNibDataService interface {
+ GetRsmGeneralConfiguration() (*models.RsmGeneralConfiguration, error)
+ SaveRsmGeneralConfiguration(config *models.RsmGeneralConfiguration) error
+ GetRsmRanInfo(ranName string) (*models.RsmRanInfo, error)
+ SaveRsmRanInfo(rsmData *models.RsmRanInfo) error
GetNodeb(ranName string) (*entities.NodebInfo, error)
GetListNodebIds() ([]*entities.NbIdentity, error)
+ GetListEnbIds() ([]*entities.NbIdentity, error)
PingRnib() bool
}
type rNibDataService struct {
- logger *logger.Logger
- rnibReaderProvider func() reader.RNibReader
- maxAttempts int
- retryInterval time.Duration
+ logger *logger.Logger
+ rnibReader reader.RNibReader
+ rsmReader rsmdb.RsmReader
+ rsmWriter rsmdb.RsmWriter
+ maxAttempts int
+ retryInterval time.Duration
}
-func NewRnibDataService(logger *logger.Logger, config *configuration.Configuration, rnibReaderProvider func() reader.RNibReader) *rNibDataService {
+func NewRnibDataService(logger *logger.Logger, config *configuration.Configuration, rnibReader reader.RNibReader, rsmReader rsmdb.RsmReader, rsmWriter rsmdb.RsmWriter) *rNibDataService {
return &rNibDataService{
- logger: logger,
- rnibReaderProvider: rnibReaderProvider,
- maxAttempts: config.Rnib.MaxRnibConnectionAttempts,
- retryInterval: time.Duration(config.Rnib.RnibRetryIntervalMs) * time.Millisecond,
+ logger: logger,
+ rnibReader: rnibReader,
+ rsmReader: rsmReader,
+ rsmWriter: rsmWriter,
+ maxAttempts: config.Rnib.MaxRnibConnectionAttempts,
+ retryInterval: time.Duration(config.Rnib.RnibRetryIntervalMs) * time.Millisecond,
}
}
-func (w *rNibDataService) GetNodeb(ranName string) (*entities.NodebInfo, error) {
- w.logger.Infof("#RnibDataService.GetNodeb - ranName: %s", ranName)
+func (w *rNibDataService) GetRsmGeneralConfiguration() (*models.RsmGeneralConfiguration, error) {
+ var rsmGeneralConfiguration *models.RsmGeneralConfiguration = nil
+
+ err := w.retry("GetRsmGeneralConfiguration", func() (err error) {
+ rsmGeneralConfiguration, err = w.rsmReader.GetRsmGeneralConfiguration()
+ return
+ })
+
+ if err == nil {
+ w.logger.Infof("#RnibDataService.GetRsmGeneralConfiguration - configuration: %+v", *rsmGeneralConfiguration)
+ }
+
+ return rsmGeneralConfiguration, err
+}
+
+func (w *rNibDataService) SaveRsmGeneralConfiguration(config *models.RsmGeneralConfiguration) error {
+ w.logger.Infof("#RnibDataService.SaveRsmGeneralConfiguration - configuration: %+v", *config)
+
+ err := w.retry("SaveRsmGeneralConfiguration", func() (err error) {
+ err = w.rsmWriter.SaveRsmGeneralConfiguration(config)
+ return
+ })
+
+ return err
+}
+
+func (w *rNibDataService) GetRsmRanInfo(ranName string) (*models.RsmRanInfo, error) {
+ var rsmRanInfo *models.RsmRanInfo = nil
+
+ err := w.retry("GetRsmRanInfo", func() (err error) {
+ rsmRanInfo, err = w.rsmReader.GetRsmRanInfo(ranName)
+ return
+ })
+
+ if err == nil {
+ w.logger.Infof("#RnibDataService.GetRsmRanInfo - RAN name: %s, RsmRanInfo: %+v", ranName, *rsmRanInfo)
+ }
+ return rsmRanInfo, err
+}
+
+func (w *rNibDataService) SaveRsmRanInfo(rsmRanInfo *models.RsmRanInfo) error {
+ err := w.retry("SaveRsmRanInfo", func() (err error) {
+ err = w.rsmWriter.SaveRsmRanInfo(rsmRanInfo)
+ return
+ })
+
+ if err == nil {
+ w.logger.Infof("#RnibDataService.SaveRsmRanInfo - RAN name: %s, RsmRanInfo: %+v", rsmRanInfo.RanName, *rsmRanInfo)
+ }
+
+ return err
+}
+
+func (w *rNibDataService) GetNodeb(ranName string) (*entities.NodebInfo, error) {
var nodeb *entities.NodebInfo = nil
err := w.retry("GetNodeb", func() (err error) {
- nodeb, err = w.rnibReaderProvider().GetNodeb(ranName)
+ nodeb, err = w.rnibReader.GetNodeb(ranName)
return
})
return nodeb, err
}
+func (w *rNibDataService) GetListEnbIds() ([]*entities.NbIdentity, error) {
+ w.logger.Infof("#RnibDataService.GetListEnbIds")
+
+ var nodeIds []*entities.NbIdentity = nil
+
+ err := w.retry("GetListEnbIds", func() (err error) {
+ nodeIds, err = w.rnibReader.GetListEnbIds()
+ return
+ })
+
+ return nodeIds, err
+}
+
func (w *rNibDataService) GetListNodebIds() ([]*entities.NbIdentity, error) {
w.logger.Infof("#RnibDataService.GetListNodebIds")
var nodeIds []*entities.NbIdentity = nil
err := w.retry("GetListNodebIds", func() (err error) {
- nodeIds, err = w.rnibReaderProvider().GetListNodebIds()
+ nodeIds, err = w.rnibReader.GetListNodebIds()
return
})
func (w *rNibDataService) PingRnib() bool {
err := w.retry("GetListNodebIds", func() (err error) {
- _, err = w.rnibReaderProvider().GetListNodebIds()
+ _, err = w.rnibReader.GetListNodebIds()
return
})
return
}
if !isRnibConnectionError(err) {
+ w.logger.Errorf("#RnibDataService - error in %s: %s", rnibFunc, err)
return err
}
if i >= attempts {
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
- "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
"github.com/stretchr/testify/assert"
"net"
"rsm/configuration"
}
config.Rnib.MaxRnibConnectionAttempts = maxAttempts
- readerMock := &mocks.RnibReaderMock{}
- rnibReaderProvider := func() reader.RNibReader {
- return readerMock
- }
+ rnibReaderMock := &mocks.RnibReaderMock{}
+ rsmReaderMock := &mocks.RsmReaderMock{}
+ rsmWriterMock := &mocks.RsmWriterMock{}
- rnibDataService := NewRnibDataService(logger, config, rnibReaderProvider)
+ rnibDataService := NewRnibDataService(logger, config, rnibReaderMock, rsmReaderMock, rsmWriterMock)
assert.NotNil(t, rnibDataService)
- return rnibDataService, readerMock
+ return rnibDataService, rnibReaderMock
}
func TestSuccessfulGetNodeb(t *testing.T) {
res, err := rnibDataService.GetNodeb(invName)
readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
- assert.True(t, strings.Contains(err.Error(), "connection error", ))
+ assert.True(t, strings.Contains(err.Error(), "connection error"))
assert.Equal(t, nodeb, res)
}
res, err := rnibDataService.GetListNodebIds()
readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 3)
- assert.True(t, strings.Contains(err.Error(), "connection error", ))
+ assert.True(t, strings.Contains(err.Error(), "connection error"))
assert.Equal(t, nodeIds, res)
}
res, err := rnibDataService.GetListNodebIds()
readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 3)
- assert.True(t, strings.Contains(err.Error(), "connection error", ))
+ assert.True(t, strings.Contains(err.Error(), "connection error"))
assert.Equal(t, nodeIds, res)
res2, err := rnibDataService.GetNodeb(invName)
readerMock.AssertNumberOfCalls(t, "GetNodeb", 3)
- assert.True(t, strings.Contains(err.Error(), "connection error", ))
+ assert.True(t, strings.Contains(err.Error(), "connection error"))
assert.Equal(t, nodeb, res2)
}
res, err := rnibDataService.GetListNodebIds()
readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 5)
- assert.True(t, strings.Contains(err.Error(), "connection error", ))
+ assert.True(t, strings.Contains(err.Error(), "connection error"))
assert.Equal(t, nodeIds, res)
}
res := rnibDataService.PingRnib()
readerMock.AssertNumberOfCalls(t, "GetListNodebIds", 1)
assert.True(t, res)
-}
+}
\ No newline at end of file
"bytes"
"encoding/json"
"net/http"
+ "rsm/enums"
+ "rsm/models"
"strconv"
)
req, _ := http.NewRequest("POST", "https://localhost:3800/request", b)
return req
}
+
+func GetRsmGeneralConfiguration(enableResourceStatus bool) *models.RsmGeneralConfiguration {
+ return &models.RsmGeneralConfiguration{
+ EnableResourceStatus: enableResourceStatus,
+ 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,
+ }
+}
\ No newline at end of file
+++ /dev/null
-//
-// Copyright 2019 AT&T Intellectual Property
-// Copyright 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.
-
-// This source code is part of the near-RT RIC (RAN Intelligent Controller)
-// platform project (RICP).
-
-
-package tests
-
-// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
-// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
-// #include <asn1codec_utils.h>
-// #include <SuccessfulOutcome.h>
-//
-// bool
-// build_pack_x2_reset_response(size_t* packed_buf_size, unsigned char* packed_buf, size_t err_buf_size, char* err_buf){
-// bool rc = true;
-// E2AP_PDU_t *pdu = calloc(1, sizeof(E2AP_PDU_t));
-// SuccessfulOutcome_t *successfulOutcome = calloc(1, sizeof(SuccessfulOutcome_t));
-// ResetResponse_t *resetResponse;
-// ResetResponse_IEs_t *resetResponse_IEs = calloc(1, sizeof(ResetResponse_IEs_t));
-//
-// assert(pdu != 0);
-// assert(successfulOutcome != 0);
-// assert(resetResponse_IEs != 0);
-//
-// pdu->present = E2AP_PDU_PR_successfulOutcome;
-// pdu->choice.successfulOutcome = successfulOutcome;
-//
-// successfulOutcome->procedureCode = ProcedureCode_id_reset;
-// successfulOutcome->criticality = Criticality_reject;
-// successfulOutcome->value.present = SuccessfulOutcome__value_PR_ResetResponse;
-// resetResponse = &successfulOutcome->value.choice.ResetResponse;
-//
-// CriticalityDiagnostics_IE_List_t *critList = calloc(1, sizeof(CriticalityDiagnostics_IE_List_t));
-// assert(critList != 0);
-// resetResponse_IEs->id = ProtocolIE_ID_id_CriticalityDiagnostics;
-// resetResponse_IEs->criticality = Criticality_ignore;
-// resetResponse_IEs->value.present = ResetResponse_IEs__value_PR_CriticalityDiagnostics;
-// ASN_SEQUENCE_ADD(resetResponse_IEs->value.choice.CriticalityDiagnostics.iEsCriticalityDiagnostics,critList);
-//
-// CriticalityDiagnostics_IE_List__Member *member= calloc(1, sizeof(CriticalityDiagnostics_IE_List__Member));
-// assert(member != 0);
-// ASN_SEQUENCE_ADD(critList ,member);
-//
-// ASN_SEQUENCE_ADD(&resetResponse->protocolIEs, resetResponse_IEs);
-//
-// rc = per_pack_pdu(pdu, packed_buf_size, packed_buf,err_buf_size, err_buf);
-//
-// ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu);
-// return rc;
-// }
-import "C"
-import (
- "errors"
- "fmt"
- "unsafe"
-)
-const PackedBufferSize = 4096
-
-func BuildPackedX2ResetResponse()([]byte, error){
- payloadSize := C.ulong(PackedBufferSize)
- packedBuffer := [PackedBufferSize]C.uchar{}
- errorBuffer := [PackedBufferSize]C.char{}
- res := bool(C.build_pack_x2_reset_response(&payloadSize, &packedBuffer[0], PackedBufferSize, &errorBuffer[0]))
- if !res {
- return nil, errors.New(fmt.Sprintf("packing error: %s", C.GoString(&errorBuffer[0])))
- }
- return C.GoBytes(unsafe.Pointer(&packedBuffer), C.int(payloadSize)), nil
-}
package testhelper
import (
- "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
"rsm/configuration"
"rsm/logger"
"rsm/mocks"
t.Errorf("#tests.InitTestCase - failed to parse configuration, error: %s", err)
}
- readerMock := &mocks.RnibReaderMock{}
- rnibReaderProvider := func() reader.RNibReader {
- return readerMock
- }
+ rnibReaderMock := &mocks.RnibReaderMock{}
+
+ rsmReaderMock := &mocks.RsmReaderMock{}
+ rsmWriterMock := &mocks.RsmWriterMock{}
rmrSender := InitRmrSender(&mocks.RmrMessengerMock{}, logger)
- rnibDataService := services.NewRnibDataService(logger, config, rnibReaderProvider)
+ rnibDataService := services.NewRnibDataService(logger, config, rnibReaderMock, rsmReaderMock, rsmWriterMock)
return rnibDataService, rmrSender, logger
}