From 2fc6c62c6c2e3957185676bc4db287d53ddc4b38 Mon Sep 17 00:00:00 2001 From: porosnicuadrian Date: Thu, 17 Dec 2020 17:57:46 +0200 Subject: [PATCH] Integration and unit tests in loaders for coverage --- loaders/lib_test.go | 95 ++++++++++++++++++++++++ loaders/loader_it_test.go | 152 ++++++++++++++++++++++++++++++++++++++ loaders/loader_test.go | 104 ++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) diff --git a/loaders/lib_test.go b/loaders/lib_test.go index 16aaf4aa6..b154f8dda 100644 --- a/loaders/lib_test.go +++ b/loaders/lib_test.go @@ -19,12 +19,19 @@ along with this program. If not, see package loaders import ( + "encoding/csv" "errors" "flag" + "io/ioutil" "net/rpc" "net/rpc/jsonrpc" + "strings" + "testing" + + "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) @@ -49,3 +56,91 @@ func newRPCClient(cfg *config.ListenCfg) (c *rpc.Client, err error) { return nil, errors.New("UNSUPPORTED_RPC") } } + +type testMockCacheConn struct { + calls map[string]func(arg interface{}, rply interface{}) error +} + +func (s *testMockCacheConn) Call(method string, arg interface{}, rply interface{}) error { + if call, has := s.calls[method]; !has { + return rpcclient.ErrUnsupporteServiceMethod + } else { + return call(arg, rply) + } +} + +func TestProcessContentCalls(t *testing.T) { + sMock := &testMockCacheConn{ + calls: map[string]func(arg interface{}, rply interface{}) error{ + utils.CacheSv1ReloadCache: func(arg interface{}, rply interface{}) error { + prply, can := rply.(*string) + if !can { + t.Errorf("Wrong argument type : %T", rply) + return nil + } + *prply = utils.OK + return nil + }, + utils.CacheSv1Clear: func(arg interface{}, rply interface{}) error { + prply, can := rply.(*string) + if !can { + t.Errorf("Wrong argument type : %T", rply) + return nil + } + *prply = utils.OK + return nil + }, + }, + } + data := engine.NewInternalDB(nil, nil, true) + + internalCacheSChan := make(chan rpcclient.ClientConnector, 1) + internalCacheSChan <- sMock + ldr := &Loader{ + ldrID: "TestProcessContentCalls", + bufLoaderData: make(map[string][]LoaderData), + connMgr: engine.NewConnManager(config.CgrConfig(), map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): internalCacheSChan, + }), + dm: engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil), + cacheConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)}, + timezone: "UTC", + } + ldr.dataTpls = map[string][]*config.FCTemplate{ + utils.MetaRateProfiles: { + {Tag: "TenantID", + Path: "Tenant", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.0", utils.INFIELD_SEP), + Mandatory: true}, + {Tag: "ProfileID", + Path: "ID", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.1", utils.INFIELD_SEP), + Mandatory: true}, + {Tag: "Weight", + Path: "Weight", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.2", utils.INFIELD_SEP)}, + }, + } + thresholdsCsv := ` +#Tenant[0],ID[1],Weight[2] +cgrates.org,MOCK_RELOAD_ID,20 +` + rdr := ioutil.NopCloser(strings.NewReader(thresholdsCsv)) + rdrCsv := csv.NewReader(rdr) + rdrCsv.Comment = '#' + ldr.rdrs = map[string]map[string]*openedCSVFile{ + utils.MetaRateProfiles: { + utils.RateProfilesCsv: &openedCSVFile{ + fileName: utils.RateProfilesCsv, + rdr: rdr, + csvRdr: rdrCsv, + }, + }, + } + if err := ldr.processContent(utils.MetaRateProfiles, utils.MetaReload); err != nil { + t.Error(err) + } +} diff --git a/loaders/loader_it_test.go b/loaders/loader_it_test.go index d8b0c7d28..b0bf6def0 100644 --- a/loaders/loader_it_test.go +++ b/loaders/loader_it_test.go @@ -20,12 +20,14 @@ along with this program. If not, see package loaders import ( + "encoding/csv" "io/ioutil" "net/rpc" "os" "path" "reflect" "sort" + "strings" "testing" "time" @@ -48,6 +50,9 @@ var ( testLoaderStartEngine, testLoaderRPCConn, testLoaderPopulateData, + testLoadFromFilesCsvActionProfile, + testLoadFromFilesCsvActionProfileOpenError, + testLoadFromFilesCsvActionProfileLockFolderError, testLoaderLoadAttributes, testLoaderVerifyOutDir, testLoaderCheckAttributes, @@ -399,3 +404,150 @@ func testLoaderVerifyOutDirForCustomSep(t *testing.T) { t.Errorf("Expecting: %q, received: %q", customAttributes, string(outContent1)) } } + +func testLoadFromFilesCsvActionProfile(t *testing.T) { + flPath := "/tmp/TestLoadFromFilesCsvActionProfile" + if err := os.MkdirAll(flPath, 0777); err != nil { + t.Error(err) + } + newFile, err := os.Create(path.Join(flPath, "ActionProfiles.csv")) + if err != nil { + t.Error(err) + } + newFile.Write([]byte(` +#Tenant[0],ID[1] +cgrates.org,SET_ACTPROFILE_3 +`)) + content, err := ioutil.ReadFile(path.Join(flPath, "ActionProfiles.csv")) + if err != nil { + t.Error(err) + } + newFile.Close() + + data := engine.NewInternalDB(nil, nil, true) + ldr := &Loader{ + ldrID: "TestRemoveActionProfileContent", + bufLoaderData: make(map[string][]LoaderData), + dm: engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil), + tpInDir: flPath, + tpOutDir: utils.EmptyString, + lockFilename: "ActionProfiles.csv", + fieldSep: ",", + timezone: "UTC", + } + ldr.dataTpls = map[string][]*config.FCTemplate{ + utils.MetaActionProfiles: { + {Tag: "TenantID", + Path: "Tenant", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.0", utils.INFIELD_SEP), + Mandatory: true}, + {Tag: "ProfileID", + Path: "ID", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.1", utils.INFIELD_SEP), + Mandatory: true}, + }, + } + + rdr := ioutil.NopCloser(strings.NewReader(string(content))) + csvRdr := csv.NewReader(rdr) + csvRdr.Comment = '#' + ldr.rdrs = map[string]map[string]*openedCSVFile{ + utils.MetaActionProfiles: { + utils.ActionProfilesCsv: &openedCSVFile{ + fileName: utils.ActionProfilesCsv, + rdr: rdr, + csvRdr: csvRdr, + }, + }, + } + if err := ldr.ProcessFolder(utils.EmptyString, utils.MetaStore, true); err != nil { + t.Error(err) + } + expACtPrf := &engine.ActionProfile{ + Tenant: "cgrates.org", + ID: "SET_ACTPROFILE_3", + FilterIDs: []string{}, + Targets: map[string]utils.StringSet{}, + Actions: []*engine.APAction{}, + } + if rcv, err := ldr.dm.GetActionProfile(expACtPrf.Tenant, expACtPrf.ID, + true, true, utils.NonTransactional); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expACtPrf, rcv) { + t.Errorf("Expected %+v, received %+v", utils.ToJSON(expACtPrf), utils.ToJSON(rcv)) + } + + //checking the error by adding a caching method + ldr.connMgr = engine.NewConnManager(config.NewDefaultCGRConfig(), nil) + ldr.cacheConns = []string{utils.MetaInternal} + rdr = ioutil.NopCloser(strings.NewReader(string(content))) + csvRdr = csv.NewReader(rdr) + csvRdr.Comment = '#' + ldr.rdrs = map[string]map[string]*openedCSVFile{ + utils.MetaActionProfiles: { + utils.ActionProfilesCsv: &openedCSVFile{ + fileName: utils.ActionProfilesCsv, + rdr: rdr, + csvRdr: csvRdr, + }, + }, + } + expected := "UNSUPPORTED_SERVICE_METHOD" + if err := ldr.ProcessFolder(utils.MetaReload, utils.MetaStore, true); err == nil || err.Error() != expected { + t.Error(err) + } + + if err = os.RemoveAll(flPath); err != nil { + t.Fatal(err) + } +} + +func testLoadFromFilesCsvActionProfileOpenError(t *testing.T) { + data := engine.NewInternalDB(nil, nil, true) + ldr := &Loader{ + ldrID: "TestRemoveActionProfileContent", + bufLoaderData: make(map[string][]LoaderData), + dm: engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil), + tpInDir: "/tmp/testLoadFromFilesCsvActionProfileOpenError", + timezone: "UTC", + } + ldr.rdrs = map[string]map[string]*openedCSVFile{ + utils.MetaActionProfiles: { + utils.ActionProfilesCsv: &openedCSVFile{ + fileName: utils.ActionProfilesCsv, + }, + }, + } + expectedErr := "open /tmp/testLoadFromFilesCsvActionProfileOpenError/ActionProfiles.csv: not a directory" + if err := ldr.ProcessFolder(utils.EmptyString, utils.MetaStore, true); err == nil || err.Error() != expectedErr { + t.Errorf("Expected %+v, received %+v", expectedErr, err) + } + + //if stopOnError is on true, the error is avoided,but instead will get a logger.warning message + if err := ldr.ProcessFolder(utils.EmptyString, utils.MetaStore, false); err != nil { + t.Error(err) + } +} + +func testLoadFromFilesCsvActionProfileLockFolderError(t *testing.T) { + data := engine.NewInternalDB(nil, nil, true) + ldr := &Loader{ + ldrID: "TestRemoveActionProfileContent", + bufLoaderData: make(map[string][]LoaderData), + dm: engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil), + timezone: "UTC", + } + ldr.rdrs = map[string]map[string]*openedCSVFile{ + utils.MetaActionProfiles: { + utils.ActionProfilesCsv: &openedCSVFile{ + fileName: utils.ActionProfilesCsv, + }, + }, + } + expectedErr := "open : no such file or directory" + if err := ldr.ProcessFolder(utils.EmptyString, utils.MetaStore, true); err == nil || err.Error() != expectedErr { + t.Errorf("Expected %+v, received %+v", expectedErr, err) + } +} diff --git a/loaders/loader_test.go b/loaders/loader_test.go index b4acf3755..521f8b011 100644 --- a/loaders/loader_test.go +++ b/loaders/loader_test.go @@ -4088,3 +4088,107 @@ cgrates.org,REM_ACTPROFILE_1 t.Error(err) } } + +func TestRemoveContentError1(t *testing.T) { + //use actionProfile to generate an error by giving a wrong csv + data := engine.NewInternalDB(nil, nil, true) + ldr := &Loader{ + ldrID: "TestRemoveActionProfileContent", + bufLoaderData: make(map[string][]LoaderData), + dm: engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil), + timezone: "UTC", + } + ldr.dataTpls = map[string][]*config.FCTemplate{ + utils.MetaActionProfiles: { + {Tag: "TenantID", + Path: "Tenant", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.0", utils.INFIELD_SEP), + Mandatory: true}, + {Tag: "ProfileID", + Path: "ID", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.1", utils.INFIELD_SEP), + Mandatory: true}, + }, + } + //wrong start at the beginning of csv + actPrfCsv := ` +//Tenant[0] +cgrates.org,REM_ACTPROFILE_s +` + rdr := ioutil.NopCloser(strings.NewReader(actPrfCsv)) + csvRdr := csv.NewReader(rdr) + csvRdr.Comment = '#' + ldr.rdrs = map[string]map[string]*openedCSVFile{ + utils.MetaActionProfiles: { + utils.ActionProfilesCsv: &openedCSVFile{ + fileName: utils.ActionProfilesCsv, + rdr: rdr, + csvRdr: csvRdr, + }, + }, + } + actRtPrf := &engine.ActionProfile{ + Tenant: "cgrates.org", + ID: "REM_ACTPROFILE_s", + } + expectedErr := "NOT_FOUND" + if err := ldr.dm.SetActionProfile(actRtPrf, true); err != nil { + t.Error(err) + } else if err := ldr.removeContent(utils.MetaActionProfiles, utils.EmptyString); err == nil || err.Error() != expectedErr { + t.Errorf("Expected %+v, received %+v", expectedErr, err) + } +} + +func TestRemoveContentError2(t *testing.T) { + //use actionProfile to generate an error by giving a wrong csv + data := engine.NewInternalDB(nil, nil, true) + ldr := &Loader{ + ldrID: "TestRemoveActionProfileContent", + bufLoaderData: make(map[string][]LoaderData), + dm: engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil), + timezone: "UTC", + } + ldr.dataTpls = map[string][]*config.FCTemplate{ + utils.MetaActionProfiles: { + {Tag: "TenantID", + Path: "Tenant", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.0", utils.INFIELD_SEP), + Mandatory: true}, + {Tag: "ProfileID", + Path: "ID", + Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.1", utils.INFIELD_SEP), + Mandatory: true}, + }, + } + //wrong start at the beginning of csv + actPrfCsv := ` +Tenant[0],ID[1] +cgrates.org,REM_ACTPROFILE_s +` + rdr := ioutil.NopCloser(strings.NewReader(actPrfCsv)) + csvRdr := csv.NewReader(rdr) + csvRdr.Comment = '#' + ldr.rdrs = map[string]map[string]*openedCSVFile{ + utils.MetaActionProfiles: { + utils.ActionProfilesCsv: &openedCSVFile{ + fileName: utils.ActionProfilesCsv, + rdr: rdr, + csvRdr: csvRdr, + }, + }, + } + actRtPrf := &engine.ActionProfile{ + Tenant: "cgrates.org", + ID: "REM_ACTPROFILE_s", + } + expectedErr := "NOT_FOUND" + if err := ldr.dm.SetActionProfile(actRtPrf, true); err != nil { + t.Error(err) + } else if err := ldr.removeContent(utils.MetaActionProfiles, utils.EmptyString); err == nil || err.Error() != expectedErr { + t.Errorf("Expected %+v, received %+v", expectedErr, err) + } +}