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)
}
}