From 03b838962ad40513aba6c36ae04c989bdc8f75a0 Mon Sep 17 00:00:00 2001 From: gezimbll Date: Fri, 16 Dec 2022 10:45:03 -0500 Subject: [PATCH] Improving coverage at engine --- engine/actions_test.go | 10 +++ engine/cdrs_test.go | 177 +++++++++++++++++++++++++++++++++++-- engine/datamanager_test.go | 163 ++++++++++++++++++++++++++++++++++ engine/dynamicdp_test.go | 86 ++++++++++++++---- 4 files changed, 414 insertions(+), 22 deletions(-) diff --git a/engine/actions_test.go b/engine/actions_test.go index c58d5fdf4..7d00dc15b 100644 --- a/engine/actions_test.go +++ b/engine/actions_test.go @@ -3446,7 +3446,13 @@ func TestRemoveSessionCost(t *testing.T) { tmp := Cache tmpCdr := cdrStorage tmpDm := dm + utils.Logger.SetLogLevel(4) + utils.Logger.SetSyslog(nil) + buf := new(bytes.Buffer) + log.SetOutput(buf) defer func() { + utils.Logger.SetLogLevel(0) + log.SetOutput(os.Stderr) Cache = tmp cdrStorage = tmpCdr dm = tmpDm @@ -3488,9 +3494,13 @@ func TestRemoveSessionCost(t *testing.T) { }, }, []string{"grpId"}, true, utils.NonTransactional) SetCdrStorage(db) + expLog := `for filter` if err := removeSessionCosts(nil, action, nil, nil, nil); err == nil || err != utils.ErrNotFound { t.Error(err) + } else if rcvLog := buf.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) } + } func TestLogAction(t *testing.T) { diff --git a/engine/cdrs_test.go b/engine/cdrs_test.go index 8af296608..3a75d0256 100644 --- a/engine/cdrs_test.go +++ b/engine/cdrs_test.go @@ -19,8 +19,12 @@ along with this program. If not, see package engine import ( + "bytes" "fmt" + "log" + "os" "reflect" + "strings" "testing" "time" @@ -245,8 +249,11 @@ func TestArgV1ProcessClone(t *testing.T) { } func TestCDRV1GetCDRs(t *testing.T) { + cfg := config.NewDefaultCGRConfig() - cfg.GeneralCfg().DefaultTimezone = "UTC" + defer func() { + config.SetCgrConfig(config.NewDefaultCGRConfig()) + }() db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) dm := NewDataManager(db, cfg.CacheCfg(), nil) cdrS := &CDRServer{ @@ -255,11 +262,21 @@ func TestCDRV1GetCDRs(t *testing.T) { cdrDb: NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items), dm: dm, } - args := &utils.RPCCDRsFilterWithAPIOpts{ + args := utils.RPCCDRsFilterWithAPIOpts{ - RPCCDRsFilter: &utils.RPCCDRsFilter{}, - Tenant: "cgrates.org", - APIOpts: map[string]interface{}{}, + RPCCDRsFilter: &utils.RPCCDRsFilter{ + CGRIDs: []string{"CGRIDs"}, + NotCGRIDs: []string{"NotCGRIDs"}, + RunIDs: []string{"RunIDs"}, + NotRunIDs: []string{"NotRunIDs"}, + OriginIDs: []string{"OriginIDs"}, + NotOriginIDs: []string{"NotOriginIDs"}, + OriginHosts: []string{"OriginHosts"}, + SetupTimeStart: "2020-04-18T11:46:26.371Z", + SetupTimeEnd: "2020-04-18T11:46:26.371Z", + }, + Tenant: "cgrates.org", + APIOpts: map[string]interface{}{}, } cdrs := &[]*CDR{ { @@ -268,8 +285,8 @@ func TestCDRV1GetCDRs(t *testing.T) { CGRID: "cgr1d", }, } - if err := cdrS.V1GetCDRs(*args, cdrs); err == nil { - t.Error(err) + if err := cdrS.V1GetCDRs(args, cdrs); err == nil || err.Error() != fmt.Sprintf("SERVER_ERROR: %s", utils.ErrNotFound) { + t.Error(utils.NewErrServerError(utils.ErrNotFound)) } } @@ -803,6 +820,9 @@ func TestCDRSV1ProcessEventCacheSet(t *testing.T) { func TestV1ProcessEvent(t *testing.T) { Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() + defer func() { + config.SetCgrConfig(cfg) + }() cfg.CdrsCfg().AttributeSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.AttributeSConnsCfg)} cfg.CdrsCfg().ChargerSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaChargers)} cfg.CdrsCfg().RaterConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaResponder)} @@ -918,6 +938,149 @@ func TestV1ProcessEvent(t *testing.T) { t.Errorf("expected %v,received %v", utils.OK, reply) } } +func TestCdrprocessEventsErrLog(t *testing.T) { + cfg := config.NewDefaultCGRConfig() + buf := new(bytes.Buffer) + setlog := func(b *bytes.Buffer) { + utils.Logger.SetLogLevel(4) + utils.Logger.SetSyslog(nil) + log.SetOutput(b) + } + setlog(buf) + removelog := func() { + utils.Logger.SetLogLevel(0) + log.SetOutput(os.Stderr) + } + tmp := Cache + defer func() { + removelog() + Cache = tmp + }() + cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ + utils.CacheCDRsTBL: { + Limit: 3, + StaticTTL: true, + }, + } + Cache.Clear(nil) + cfg.CdrsCfg().EEsConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaEEs)} + db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) + dm := NewDataManager(db, cfg.CacheCfg(), nil) + clientConn := make(chan rpcclient.ClientConnector, 1) + clientConn <- &ccMock{ + calls: map[string]func(args interface{}, reply interface{}) error{ + utils.EeSv1ProcessEvent: func(args, reply interface{}) error { + + return utils.ErrPartiallyExecuted + }, + }, + } + connMgr := NewConnManager(cfg, map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.MetaEEs): clientConn, + }) + cdrs := &CDRServer{ + cgrCfg: cfg, + cdrDb: db, + dm: dm, + connMgr: connMgr, + } + + evs := []*utils.CGREvent{ + {ID: "TestV1ProcessEventNoTenant", + Event: map[string]interface{}{ + utils.CGRID: "test1", + utils.RunID: utils.MetaDefault, + utils.OriginID: "testV1CDRsRefundOutOfSessionCost", + utils.RequestType: utils.MetaPrepaid, + utils.AccountField: "testV1CDRsRefundOutOfSessionCost", + utils.Destination: "+4986517174963", + utils.AnswerTime: time.Date(2019, 11, 27, 12, 21, 26, 0, time.UTC), + utils.Usage: 123 * time.Minute}, + }} + expLog := `with AttributeS` + if _, err := cdrs.processEvents(evs, true, true, true, true, true, true, true, true, true); err == nil || err != utils.ErrPartiallyExecuted { + t.Error(err) + } else if rcvLog := buf.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } + removelog() + buf2 := new(bytes.Buffer) + setlog(buf2) + expLog = `with ChargerS` + if _, err := cdrs.processEvents(evs, true, false, true, true, true, true, true, true, true); err == nil || err != utils.ErrPartiallyExecuted { + t.Error(err) + } else if rcvLog := buf2.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } + removelog() + buf3 := new(bytes.Buffer) + setlog(buf3) + Cache.Set(utils.CacheCDRIDs, utils.ConcatenatedKey("test1", utils.MetaDefault), "val", []string{}, true, utils.NonTransactional) + expLog = `with CacheS` + if _, err = cdrs.processEvents(evs, false, false, false, true, true, false, true, true, true); err == nil || err != utils.ErrExists { + t.Error(err) + } else if rcvLog := buf3.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } + buf4 := new(bytes.Buffer) + removelog() + setlog(buf4) + evs[0].Event[utils.AnswerTime] = "time" + expLog = `converting event` + if _, err = cdrs.processEvents(evs, false, false, true, true, true, false, true, true, true); err == nil || err != utils.ErrPartiallyExecuted { + t.Error(err) + } else if rcvLog := buf4.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } + buf5 := new(bytes.Buffer) + removelog() + setlog(buf5) + evs[0].Event[utils.AnswerTime] = time.Date(2019, 11, 27, 12, 21, 26, 0, time.UTC) + expLog = `refunding CDR` + if _, err = cdrs.processEvents(evs, false, false, true, false, false, false, false, false, false); err != nil { + t.Error(err) + } else if rcvLog := buf5.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } + db.db.Set(utils.CacheCDRsTBL, utils.ConcatenatedKey("test1", utils.MetaDefault, "testV1CDRsRefundOutOfSessionCost"), "val", []string{}, true, utils.NonTransactional) + + buf6 := new(bytes.Buffer) + removelog() + setlog(buf6) + expLog = `refunding CDR` + if _, err = cdrs.processEvents(evs, false, false, true, false, true, false, false, false, false); err == nil || err != utils.ErrExists { + t.Error(err) + } else if rcvLog := buf6.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } + buf7 := new(bytes.Buffer) + removelog() + setlog(buf7) + expLog = `exporting cdr` + if _, err = cdrs.processEvents(evs, false, false, true, false, false, true, true, false, false); err == nil || err != utils.ErrPartiallyExecuted { + t.Error(err) + } else if rcvLog := buf7.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } + buf8 := new(bytes.Buffer) + removelog() + setlog(buf8) + expLog = `processing event` + if _, err = cdrs.processEvents(evs, false, false, true, false, false, true, false, true, false); err == nil || err != utils.ErrPartiallyExecuted { + t.Error(err) + } else if rcvLog := buf8.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } + buf9 := new(bytes.Buffer) + removelog() + setlog(buf9) + expLog = `processing event` + if _, err = cdrs.processEvents(evs, false, false, true, false, false, true, false, false, true); err == nil || err != utils.ErrPartiallyExecuted { + t.Error(err) + } else if rcvLog := buf9.String(); !strings.Contains(rcvLog, expLog) { + t.Errorf("expected %v,received %v", expLog, rcvLog) + } +} func TestV1ProcessCDR(t *testing.T) { Cache.Clear(nil) diff --git a/engine/datamanager_test.go b/engine/datamanager_test.go index 6e2c41d8b..625a86e30 100644 --- a/engine/datamanager_test.go +++ b/engine/datamanager_test.go @@ -1146,3 +1146,166 @@ func TestDmSharedGroup(t *testing.T) { t.Error("should been removed") } } + +func TestDMThresholdProfile(t *testing.T) { + cfg := config.NewDefaultCGRConfig() + tmpDm := dm + tmp := Cache + defer func() { + config.SetCgrConfig(config.NewDefaultCGRConfig()) + Cache = tmp + SetDataStorage(tmpDm) + }() + Cache.Clear(nil) + cfg.DataDbCfg().RplConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} + cfg.DataDbCfg().RplFiltered = true + cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ + utils.CacheThresholdProfiles: { + Limit: 3, + Replicate: true, + APIKey: "key", + RouteID: "route", + }, + utils.CacheThresholds: { + Limit: 3, + Replicate: true, + APIKey: "key", + RouteID: "route", + }, + } + clientConn := make(chan rpcclient.ClientConnector, 1) + clientConn <- &ccMock{ + calls: map[string]func(args interface{}, reply interface{}) error{ + utils.ReplicatorSv1SetThresholdProfile: func(args, reply interface{}) error { + thPApiOpts, cancast := args.(ThresholdProfileWithAPIOpts) + if !cancast { + return utils.ErrNotConvertible + } + dm.DataDB().SetThresholdProfileDrv(thPApiOpts.ThresholdProfile) + return nil + }, + utils.ReplicatorSv1SetThreshold: func(args, reply interface{}) error { + thApiOpts, cancast := args.(ThresholdWithAPIOpts) + if !cancast { + return utils.ErrNotConvertible + } + dm.DataDB().SetThresholdDrv(thApiOpts.Threshold) + return nil + }, + utils.ReplicatorSv1RemoveThresholdProfile: func(args, reply interface{}) error { + tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) + if !cancast { + return utils.ErrNotConvertible + } + dm.DataDB().RemThresholdProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) + return nil + }, + }, + } + db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) + connMgr := NewConnManager(cfg, map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, + }) + dm := NewDataManager(db, cfg.CacheCfg(), connMgr) + config.SetCgrConfig(cfg) + SetDataStorage(dm) + th := &ThresholdProfile{ + Tenant: "cgrates.org", + ID: "THD_Test", + FilterIDs: []string{"*string:Account:test"}, + MaxHits: -1, + MinSleep: time.Second, + Blocker: false, + Weight: 20.0, + ActionIDs: []string{"ACT_LOG"}, + Async: false, + } + if err := dm.SetThresholdProfile(th, false); err != nil { + t.Error(err) + } + if val, err := dm.GetThresholdProfile(th.Tenant, th.ID, true, false, utils.NonTransactional); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(th, val) { + t.Errorf("expected %v,received %v", utils.ToJSON(th), utils.ToJSON(val)) + } + if err := dm.RemoveThresholdProfile(th.Tenant, th.ID, false); err != nil { + t.Error(err) + } + if _, has := db.db.Get(utils.CacheThresholdProfiles, utils.ConcatenatedKey(th.Tenant, th.ID)); has { + t.Error("should receive error") + } +} + +func TestDmDispatcherHost(t *testing.T) { + cfg := config.NewDefaultCGRConfig() + tmpDm := dm + tmp := Cache + defer func() { + config.SetCgrConfig(config.NewDefaultCGRConfig()) + Cache = tmp + SetDataStorage(tmpDm) + }() + Cache.Clear(nil) + cfg.DataDbCfg().RplConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} + cfg.DataDbCfg().RplFiltered = true + cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ + utils.CacheDispatcherHosts: { + Limit: 3, + Replicate: true, + APIKey: "key", + RouteID: "route", + }, + } + clientConn := make(chan rpcclient.ClientConnector, 1) + clientConn <- &ccMock{ + calls: map[string]func(args interface{}, reply interface{}) error{ + utils.ReplicatorSv1SetDispatcherHost: func(args, reply interface{}) error { + dspApiOpts, cancast := args.(DispatcherHostWithAPIOpts) + if !cancast { + return utils.ErrNotConvertible + } + dm.DataDB().SetDispatcherHostDrv(dspApiOpts.DispatcherHost) + return nil + }, + utils.ReplicatorSv1RemoveDispatcherHost: func(args, reply interface{}) error { + tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) + if !cancast { + return utils.ErrNotConvertible + } + dm.DataDB().RemoveDispatcherHostDrv(tntApiOpts.Tenant, tntApiOpts.ID) + return nil + }, + }, + } + db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) + connMgr := NewConnManager(cfg, map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, + }) + dm := NewDataManager(db, cfg.CacheCfg(), connMgr) + config.SetCgrConfig(cfg) + SetDataStorage(dm) + + dH := &DispatcherHost{ + Tenant: "testTenant", + RemoteHost: &config.RemoteHost{ + ID: "testID", + Address: rpcclient.InternalRPC, + Transport: utils.MetaInternal, + TLS: false, + }, + } + if err := dm.SetDispatcherHost(dH); err != nil { + t.Error(err) + } + if val, err := dm.GetDispatcherHost(dH.Tenant, dH.ID, true, false, utils.NonTransactional); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(dH, val) { + t.Errorf("expected %v,received %v", utils.ToJSON(dH), utils.ToJSON(val)) + } + if err = dm.RemoveDispatcherHost(dH.Tenant, dH.ID); err != nil { + t.Error(err) + } + if _, has := db.db.Get(utils.CacheDispatcherHosts, utils.ConcatenatedKey(dH.Tenant, dH.ID)); has { + t.Error("has not been removed from the cache") + } +} diff --git a/engine/dynamicdp_test.go b/engine/dynamicdp_test.go index 9b30b0f11..7e36a8f19 100644 --- a/engine/dynamicdp_test.go +++ b/engine/dynamicdp_test.go @@ -18,7 +18,6 @@ along with this program. If not, see package engine import ( - "fmt" "testing" "github.com/cgrates/cgrates/config" @@ -59,31 +58,88 @@ func TestDynamicDpFieldAsInterface(t *testing.T) { } -func TestDpLibPhoneNumber(t *testing.T) { - num, err := phonenumbers.ParseAndKeepRawInput("+3554735474", utils.EmptyString) +func TestDDPFieldAsInterface(t *testing.T) { + libDP, err := newLibPhoneNumberDP("+447975777666") if err != nil { t.Error(err) } + phoneNm, canCast := libDP.(*libphonenumberDP) + if !canCast { + t.Error("can't convert interface") + } dDP := &libphonenumberDP{ - pNumber: num, - cache: utils.MapStorage{}, + pNumber: phoneNm.pNumber, + cache: utils.MapStorage{ + "field": "val", + }, } - dDP.setDefaultFields() - if _, err := dDP.fieldAsInterface([]string{}); err == nil || err.Error() != fmt.Sprintf("invalid field path <%+v> for libphonenumberDP", []string{}) { + dDP.pNumber.Extension = utils.StringPointer("+") + dDP.pNumber.PreferredDomesticCarrierCode = utils.StringPointer("49 172") + + if val, err := dDP.fieldAsInterface([]string{"CountryCode"}); err != nil { t.Error(err) + } else if val.(int32) != int32(44) { + t.Errorf("expected %v,reveived %v", 44, val.(int32)) } - val, err := dDP.fieldAsInterface([]string{"CountryCode"}) - if err != nil { + if val, err := dDP.fieldAsInterface([]string{"NationalNumber"}); err != nil { t.Error(err) + } else if val.(uint64) != uint64(7975777666) { + t.Errorf("expected %v,reveived %v", 7975777666, val) } - if err != nil { + if val, err := dDP.fieldAsInterface([]string{"Region"}); err != nil { t.Error(err) + } else if val.(string) != "GB" { + t.Errorf("expected %v,reveived %v", "GB", val) } - exp := int32(355) - if nationalNumber, cancast := val.(int32); !cancast { - t.Error("can't convert") - } else if nationalNumber != exp { - t.Errorf("expected %v,received %v", exp, nationalNumber) + if val, err := dDP.fieldAsInterface([]string{"NumberType"}); err != nil { + t.Error(err) + } else if val.(phonenumbers.PhoneNumberType) != 1 { + t.Errorf("expected %v,reveived %v", 1, val) + } + if val, err := dDP.fieldAsInterface([]string{"GeoLocation"}); err != nil { + t.Error(err) + } else if val.(string) != "United Kingdom" { + t.Errorf("expected %v,reveived %v", "United Kingdom", val) + } + if val, err := dDP.fieldAsInterface([]string{"Carrier"}); err != nil { + t.Error(err) + } else if val.(string) != "Orange" { + t.Errorf("expected %v,reveived %v", "Orange", val) + } + if val, err := dDP.fieldAsInterface([]string{"LengthOfNationalDestinationCode"}); err != nil { + t.Error(err) + } else if val.(int) != 0 { + t.Errorf("expected %v,reveived %v", 0, val) + } + if val, err := dDP.fieldAsInterface([]string{"RawInput"}); err != nil { + t.Error(err) + } else if val.(string) != "+447975777666" { + t.Errorf("expected %v,reveived %v", "+447975777666", val) + } + if val, err := dDP.fieldAsInterface([]string{"Extension"}); err != nil { + t.Error(err) + } else if val.(string) != "+" { + t.Errorf("expected %v,reveived %v", "+", val) + } + if val, err := dDP.fieldAsInterface([]string{"NumberOfLeadingZeros"}); err != nil { + t.Error(err) + } else if val.(int32) != int32(1) { + t.Errorf("expected %v,reveived %v", int32(1), val) + } + if val, err := dDP.fieldAsInterface([]string{"ItalianLeadingZero"}); err != nil { + t.Error(err) + } else if val.(bool) != false { + t.Errorf("expected %v,reveived %v", false, val) + } + if val, err := dDP.fieldAsInterface([]string{"PreferredDomesticCarrierCode"}); err != nil { + t.Error(err) + } else if val.(string) != "49 172" { + t.Errorf("expected %v,reveived %v", "49 172", val) + } + if val, err := dDP.fieldAsInterface([]string{"CountryCodeSource"}); err != nil { + t.Error(err) + } else if val.(phonenumbers.PhoneNumber_CountryCodeSource) != phonenumbers.PhoneNumber_CountryCodeSource(1) { + t.Errorf("expected %v,reveived %v", 1, val) } }