/* Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments Copyright (C) ITsysCOM GmbH This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see */ package engine import ( "errors" "fmt" "reflect" "slices" "testing" "time" "github.com/cgrates/birpc" "github.com/cgrates/birpc/context" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" ) func TestDmGetDestinationRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RmtConnID = "rmt" cfg.GeneralCfg().NodeID = "node" cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheDestinations: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetDestination: func(ctx *context.Context, args, reply any) error { rpl := &Destination{ Id: "nat", Prefixes: []string{"0257", "0256", "0723"}, } *reply.(**Destination) = rpl return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) exp := &Destination{ Id: "nat", Prefixes: []string{"0257", "0256", "0723"}, } dm := NewDataManager(db, cfg.CacheCfg(), connMgr) config.SetCgrConfig(cfg) SetDataStorage(dm) if val, err := dm.GetDestination("key", false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, exp) { t.Errorf("expected %+v,received %+v", utils.ToJSON(exp), utils.ToJSON(val)) } } func TestDmGetAccountRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RmtConnID = "rmt" cfg.GeneralCfg().NodeID = "node" cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheAccounts: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetAccount: func(ctx *context.Context, args, reply any) error { rpl := &Account{ ID: "cgrates.org:exp", UpdateTime: time.Now(), } *reply.(**Account) = rpl return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) exp := &Account{ ID: "cgrates.org:exp", UpdateTime: time.Now(), } dm := NewDataManager(db, cfg.CacheCfg(), connMgr) config.SetCgrConfig(cfg) SetDataStorage(dm) if val, err := dm.GetAccount("id"); err != nil { t.Error(err) } else if !reflect.DeepEqual(val.ID, exp.ID) { t.Errorf("expected %+v,received %+v", utils.ToJSON(exp), utils.ToJSON(val)) } } func TestDmGetFilterRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RmtConnID = "rmt" cfg.GeneralCfg().NodeID = "node" cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheFilters: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetFilter: func(ctx *context.Context, args, reply any) error { rpl := &Filter{ Tenant: "cgrates.org", ID: "Filter1", Rules: []*FilterRule{ { Element: "~*req.Account", Type: utils.MetaString, Values: []string{"1001", "1002"}, }, }, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), }, } *reply.(**Filter) = rpl return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) exp := &Filter{ Tenant: "cgrates.org", ID: "Filter1", Rules: []*FilterRule{ { Element: "~*req.Account", Type: utils.MetaString, Values: []string{"1001", "1002"}, }, }, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), }, } if val, err := dm.GetFilter("cgrates", "id2", false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(exp.ID, val.ID) { t.Errorf("expected %+v,received %+v", utils.ToJSON(exp), utils.ToJSON(val)) } } func TestDMGetThresholdRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.CacheCfg().Partitions[utils.CacheThresholds].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheThresholds: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetThreshold: func(ctx *context.Context, args, reply any) error { rpl := &Threshold{ Tenant: "cgrates.org", ID: "THD_ACNT_1001", Hits: 0, } *reply.(**Threshold) = rpl return nil }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) config.SetCgrConfig(cfg) SetDataStorage(dm) exp := &Threshold{ Tenant: "cgrates.org", ID: "THD_ACNT_1001", Hits: 0, } if val, err := dm.GetThreshold("cgrates", "id2", false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(exp, val) { t.Errorf("expected %+v,received %+v", utils.ToJSON(exp), utils.ToJSON(val)) } Cache.Set(utils.CacheThresholds, utils.ConcatenatedKey("cgrates.org", "THD_ACNT_1001"), nil, []string{}, false, utils.NonTransactional) if _, err := dm.GetThreshold("cgrates.org", "THD_ACNT_1001", true, true, utils.NonTransactional); err != nil { t.Error(err) } SetConnManager(connMgr) Cache = NewCacheS(cfg, dm, nil) if _, err := dm.GetThreshold("cgrates", "id2", false, true, utils.NonTransactional); err == nil || err.Error() != "Can't Replicate" { t.Error(err) } } func TestDMGetThresholdRemoteErr(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.CacheCfg().Partitions[utils.CacheThresholds].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheThresholds: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetThreshold: func(ctx *context.Context, args, reply any) error { return utils.ErrNotFound }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) config.SetCgrConfig(cfg) SetDataStorage(dm) SetConnManager(connMgr) Cache = NewCacheS(cfg, dm, nil) if _, err := dm.GetThreshold("cgrates", "id2", false, true, utils.NonTransactional); err == nil || err.Error() != "Can't Replicate" { t.Error(err) } } func TestDMGetThresholdProfileRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.CacheCfg().Partitions[utils.CacheThresholdProfiles].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheThresholdProfiles: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetThresholdProfile: func(ctx *context.Context, args, reply any) error { rpl := &ThresholdProfile{ Tenant: "cgrates.org", ID: "ID", } *reply.(**ThresholdProfile) = rpl return nil }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) config.SetCgrConfig(cfg) SetDataStorage(dm) exp := &ThresholdProfile{ Tenant: "cgrates.org", ID: "ID", } if val, err := dm.GetThresholdProfile("cgrates", "id2", false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(exp, val) { t.Errorf("expected %+v,received %+v", utils.ToJSON(exp), utils.ToJSON(val)) } Cache = NewCacheS(cfg, dm, nil) SetConnManager(connMgr) if _, err := dm.GetThresholdProfile("cgrates", "id2", false, true, utils.NonTransactional); err == nil || err.Error() != "Can't Replicate" { t.Error(err) } } func TestDMGetThresholdProfileRemoteErr(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.CacheCfg().Partitions[utils.CacheThresholdProfiles].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheThresholdProfiles: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetThresholdProfile: func(ctx *context.Context, args, reply any) error { return utils.ErrNotFound }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) config.SetCgrConfig(cfg) SetDataStorage(dm) SetConnManager(connMgr) Cache = NewCacheS(cfg, dm, nil) if _, err := dm.GetThresholdProfile("cgrates", "id2", false, true, utils.NonTransactional); err == nil || err.Error() != "Can't Replicate" { t.Error(err) } var dm2 *DataManager if _, err := dm2.GetThresholdProfile("cgrates", "id2", false, true, utils.NonTransactional); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestDMGetStatQueue(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RmtConnID = "rmt" cfg.GeneralCfg().NodeID = "node" cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheStatQueues: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetStatQueue: func(ctx *context.Context, args, reply any) error { rpl := &StatQueue{ Tenant: "cgrates.org", ID: "StatsID", SQItems: []SQItem{{ EventID: "ev1", }}, } *reply.(**StatQueue) = rpl return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) dm.ms = &JSONMarshaler{} config.SetCgrConfig(cfg) SetDataStorage(dm) exp := &StatQueue{ Tenant: "cgrates.org", ID: "StatsID", SQItems: []SQItem{{ EventID: "ev1", }}, } if val, err := dm.GetStatQueue("cgrates", "id2", false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(exp, val) { t.Errorf("expected %+v,received %+v", utils.ToJSON(exp), utils.ToJSON(val)) } } func TestRebuildReverseForPrefix(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().Items = map[string]*config.ItemOpt{ utils.CacheReverseDestinations: { Limit: 3, Remote: true, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(db, cfg.CacheCfg(), nil) dm.dataDB = &DataDBMock{} db.db.Set(utils.CacheReverseDestinations, utils.ConcatenatedKey(utils.ReverseDestinationPrefix, "item1"), &Destination{}, []string{}, true, utils.NonTransactional) if err := dm.RebuildReverseForPrefix(utils.ReverseDestinationPrefix); err == nil || err != utils.ErrNotImplemented { t.Error(err) } dm.dataDB = db if err := dm.RebuildReverseForPrefix(utils.ReverseDestinationPrefix); err != nil { t.Error(err) } } func TestDMSetAccount(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.CacheAccounts: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } acc := &Account{ ID: "vdf:broker", BalanceMap: map[string]Balances{ utils.MetaVoice: { &Balance{Value: 20 * float64(time.Second), DestinationIDs: utils.NewStringMap("NAT"), Weight: 10, RatingSubject: "rif"}, &Balance{Value: 100 * float64(time.Second), DestinationIDs: utils.NewStringMap("RET"), Weight: 20}, }}, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetAccount: func(ctx *context.Context, args, reply any) error { accApiOpts, cancast := args.(AccountWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetAccountDrv(accApiOpts.Account) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) dm.ms = &JSONMarshaler{} SetDataStorage(dm) if err := dm.SetAccount(acc); err != nil { t.Error(err) } var dmnil *DataManager if err = dmnil.SetAccount(acc); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } dm.dataDB = &DataDBMock{} if err = dm.SetAccount(acc); err == nil || err != utils.ErrNotImplemented { t.Error(err) } } func TestDMRemoveAccount(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.CacheAccounts: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } acc := &Account{ ID: "vdf:broker", BalanceMap: map[string]Balances{ utils.MetaVoice: { &Balance{Value: 20 * float64(time.Second), DestinationIDs: utils.NewStringMap("NAT"), Weight: 10, RatingSubject: "rif"}, &Balance{Value: 100 * float64(time.Second), DestinationIDs: utils.NewStringMap("RET"), Weight: 20}, }}, } if err = dm.dataDB.SetAccountDrv(acc); err != nil { t.Error(err) } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1RemoveAccount: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.RemoveAccountDrv(strApiOpts.Arg) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err = dm.RemoveAccount(acc.ID); err != nil { t.Error(err) } var dmnil *DataManager if err = dmnil.RemoveAccount(acc.ID); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } dm.dataDB = &DataDBMock{} if err = dm.RemoveAccount(acc.ID); err == nil || err != utils.ErrNotImplemented { t.Error(err) } } func TestDmSetFilter(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.CacheFilters: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } filter := &Filter{ Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, ID: "FLTR_CP_1", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Charger", Values: []string{"ChargerProfile1"}, }, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetFilter: func(ctx *context.Context, args, reply any) error { fltr, cancast := args.(FilterWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetFilterDrv(fltr.Filter) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err := dm.SetFilter(filter, false); err != nil { t.Error(err) } var dmnil *DataManager if err = dmnil.SetFilter(filter, false); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestDMSetThreshold(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetDataStorage(tmpDm) }() Cache.Clear(nil) 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.CacheThresholds: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } thS := &Threshold{ Tenant: "cgrates.org", ID: "THD_ACNT_1001", Hits: 0, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetThreshold: func(ctx *context.Context, args, reply any) error { thS, cancast := args.(ThresholdWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetThresholdDrv(thS.Threshold) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err = dm.SetThreshold(thS); err != nil { t.Error(err) } dm.dataDB = &DataDBMock{} if err = dm.SetThreshold(thS); err == nil || err != utils.ErrNotImplemented { t.Error(err) } } func TestDmRemoveThreshold(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.CacheThresholds: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } thS := &Threshold{ Tenant: "cgrates.org", ID: "THD_ACNT_1001", Hits: 0, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1RemoveThreshold: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.RemoveThresholdDrv(tntApiOpts.TenantID.Tenant, tntApiOpts.TenantID.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err := dm.RemoveThreshold(thS.Tenant, thS.ID); err != nil { t.Error(err) } dm.dataDB = &DataDBMock{} if err = dm.RemoveThreshold(thS.Tenant, thS.ID); err == nil || err != utils.ErrNotImplemented { t.Error(err) } } func TestDMReverseDestinationRemote(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.CacheReverseDestinations: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetReverseDestination: func(ctx *context.Context, args, reply any) error { dest, cancast := args.(Destination) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetReverseDestinationDrv(dest.Id, dest.Prefixes, utils.NonTransactional) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) dest := &Destination{ Id: "nat", Prefixes: []string{"0257", "0256", "0723"}, } if err := dm.SetReverseDestination(dest.Id, dest.Prefixes, utils.NonTransactional); err != nil { t.Error(err) } exp := []string{"nat"} for _, prf := range dest.Prefixes { if val, err := dm.dataDB.GetReverseDestinationDrv(prf, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, exp) { t.Errorf("expected %v,received %v", exp, val) } } } func TestDMStatQueueRemote(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.CacheStatQueues: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetStatQueue: func(ctx *context.Context, args, reply any) error { sqApiOpts, cancast := args.(StatQueueWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetStatQueueDrv(nil, sqApiOpts.StatQueue) return nil }, utils.ReplicatorSv1RemoveStatQueue: func(ctx *context.Context, args, reply any) error { tntIDApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.RemStatQueueDrv(tntIDApiOpts.Tenant, tntIDApiOpts.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) sq := &StatQueue{ Tenant: "cgrates.org", ID: "SQ1", SQItems: []SQItem{}, SQMetrics: map[string]StatMetric{ utils.MetaTCD: &StatTCD{ Events: make(map[string]*DurationWithCompress), }, }, } if err := dm.SetStatQueue(sq); err != nil { t.Error(err) } if val, err := dm.GetStatQueue(sq.Tenant, sq.ID, true, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, sq) { t.Errorf("expected %v,received %v", utils.ToJSON(sq), utils.ToJSON(val)) } if err = dm.RemoveStatQueue(sq.Tenant, sq.ID); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheStatQueues, utils.ConcatenatedKey(sq.Tenant, sq.ID)); has { t.Error("should been removed") } } func TestDmTimingR(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.CacheTimings: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetTiming: func(ctx *context.Context, args, reply any) error { tpTimingApiOpts, cancast := args.(utils.TPTimingWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetTimingDrv(tpTimingApiOpts.TPTiming) return nil }, utils.ReplicatorSv1RemoveTiming: func(ctx *context.Context, args, reply any) error { id, cancast := args.(string) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveTimingDrv(id) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) tp := &utils.TPTiming{ ID: "MIDNIGHT", Years: utils.Years{2020, 2019}, Months: utils.Months{1, 2, 3, 4}, MonthDays: utils.MonthDays{5, 6, 7, 8}, WeekDays: utils.WeekDays{0, 1, 2, 3}, StartTime: "00:00:00", EndTime: "00:00:01", } if err := dm.SetTiming(tp); err != nil { t.Error(err) } if val, err := dm.GetTiming(tp.ID, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(tp, val) { t.Errorf("expected %v,received %v", utils.ToJSON(tp), utils.ToJSON(val)) } if err = dm.RemoveTiming(tp.ID, utils.NonTransactional); err != nil { t.Error(err) } } func TestDMSetActionTriggers(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.CacheActionTriggers: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetActionTriggers: func(ctx *context.Context, args, reply any) error { setActTrgAOpts, cancast := args.(SetActionTriggersArgWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetActionTriggersDrv(setActTrgAOpts.Key, setActTrgAOpts.Attrs) return nil }, utils.ReplicatorSv1RemoveActionTriggers: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveActionTriggersDrv(strApiOpts.Arg) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) attrs := ActionTriggers{ &ActionTrigger{ Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MetaMonetary)}, ThresholdValue: 2, ThresholdType: utils.TriggerMaxEventCounter, ActionsID: "TEST_ACTIONS"}} if err := dm.SetActionTriggers("act_ID", attrs); err != nil { t.Error(err) } if val, err := dm.GetActionTriggers("act_ID", false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(attrs, val) { t.Errorf("expected %v,received %v", utils.ToJSON(attrs), utils.ToJSON(val)) } if err = dm.RemoveActionTriggers("act_ID", utils.NonTransactional); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheActionTriggers, "act_ID"); has { t.Error("should been removed") } } func TestDMResourceProfileRemote(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.CacheResourceProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, utils.CacheResources: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetResourceProfile: func(ctx *context.Context, args, reply any) error { rscPrflApiOpts, cancast := args.(ResourceProfileWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetResourceProfileDrv(rscPrflApiOpts.ResourceProfile) return nil }, utils.ReplicatorSv1SetResource: func(ctx *context.Context, args, reply any) error { rscApiOpts, cancast := args.(ResourceWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetResourceDrv(rscApiOpts.Resource) return nil }, utils.ReplicatorSv1RemoveResourceProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveResourceProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) rp := &ResourceProfile{ Tenant: "cgrates.org", ID: "RES_ULTIMITED", FilterIDs: []string{"*string:~*req.CustomField:UnlimitedEvent"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), }, } if err := dm.SetResourceProfile(rp, false); err != nil { t.Error(err) } if val, err := dm.GetResourceProfile(rp.Tenant, rp.ID, true, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(rp, val) { t.Errorf("expected %v,received %v", utils.ToJSON(rp), utils.ToJSON(val)) } expRes := &Resource{ Tenant: rp.Tenant, ID: rp.ID, Usages: map[string]*ResourceUsage{}, } if val, err := dm.GetResource(rp.Tenant, rp.ID, true, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(expRes, val) { t.Errorf("expected %v,received %v", utils.ToJSON(rp), utils.ToJSON(val)) } if err := dm.RemoveResourceProfile(rp.Tenant, rp.ID, false); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheResourceProfiles, utils.ConcatenatedKey(rp.Tenant, rp.ID)); has { t.Error("should been removed") } } func TestDmSharedGroup(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.CacheSharedGroups: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetSharedGroup: func(ctx *context.Context, args, reply any) error { shGrpApiOpts, cancast := args.(SharedGroupWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetSharedGroupDrv(shGrpApiOpts.SharedGroup) return nil }, utils.ReplicatorSv1RemoveSharedGroup: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveSharedGroupDrv(strApiOpts.Arg) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) sg := &SharedGroup{ Id: "SG2", AccountParameters: map[string]*SharingParameters{ "*any": { Strategy: "*lowest", RatingSubject: "one", }, }, } if err := dm.SetSharedGroup(sg); err != nil { t.Error(err) } if val, err := dm.GetSharedGroup(sg.Id, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, sg) { t.Errorf("expected %+v,received %+v", utils.ToJSON(sg), utils.ToJSON(val)) } if err := dm.RemoveSharedGroup(sg.Id, utils.NonTransactional); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheSharedGroups, sg.Id); has { 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 birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetThresholdProfile: func(ctx *context.Context, args, reply any) error { thPApiOpts, cancast := args.(ThresholdProfileWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetThresholdProfileDrv(thPApiOpts.ThresholdProfile) return nil }, utils.ReplicatorSv1SetThreshold: func(ctx *context.Context, args, reply any) error { thApiOpts, cancast := args.(ThresholdWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetThresholdDrv(thApiOpts.Threshold) return nil }, utils.ReplicatorSv1RemoveThresholdProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemThresholdProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) 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 TestDMRemoveThresholdProfileErr(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().Items = map[string]*config.ItemOpt{ utils.MetaThresholdProfiles: { Remote: true, }, } cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetThresholdProfile: func(ctx *context.Context, args, reply any) error { return fmt.Errorf("Can't Replicate") }, }, } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) Cache.Set(utils.MetaThresholdProfiles, "cgrates.org:TEST_PROFILE1", nil, []string{}, true, utils.NonTransactional) if err := dm.RemoveThresholdProfile("cgrates.org", "TEST_PROFILE1", true); err == nil || err != utils.ErrNotFound { t.Error(err) } Cache.Remove(utils.MetaThresholdProfiles, "cgrates.org:TEST_PROFILE1", true, utils.NonTransactional) var dm2 *DataManager if err = dm2.RemoveThresholdProfile("cgrates.org", "TEST_PROFILE1", true); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } dm2 = NewDataManager(db, cfg.CacheCfg(), nil) dm2.dataDB = &DataDBMock{ GetThresholdProfileDrvF: func(tenant, id string) (tp *ThresholdProfile, err error) { return }, RemThresholdProfileDrvF: func(tenant, id string) (err error) { return utils.ErrNotImplemented }, } if err = dm2.RemoveThresholdProfile("cgrates.org", "TEST_PROFILE1", true); err == nil || err != utils.ErrNotImplemented { t.Error(err) } config.SetCgrConfig(cfg) if err = dm.RemoveThresholdProfile("cgrates.org", "TEST_PROFILE1", true); err == nil || err.Error() != "Can't Replicate" { t.Error(err) } } 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 birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetDispatcherHost: func(ctx *context.Context, args, reply any) error { dspApiOpts, cancast := args.(DispatcherHostWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetDispatcherHostDrv(dspApiOpts.DispatcherHost) return nil }, utils.ReplicatorSv1RemoveDispatcherHost: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveDispatcherHostDrv(tntApiOpts.Tenant, tntApiOpts.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) 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") } } func TestGetDispatcherHostErr(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.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.CacheCfg().Partitions[utils.CacheDispatcherHosts].Replicate = true cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheDispatcherHosts: { Limit: 3, Replicate: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetDispatcherHost: func(ctx *context.Context, args, reply any) error { return utils.ErrDSPHostNotFound }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) dH := &DispatcherHost{ Tenant: "testTenant", RemoteHost: &config.RemoteHost{ ID: "testID", Address: rpcclient.InternalRPC, Transport: utils.MetaInternal, TLS: false, }, } if _, err := dm.GetDispatcherHost(dH.Tenant, dH.ID, true, true, utils.NonTransactional); err == nil || err != utils.ErrDSPHostNotFound { t.Error(err) } SetConnManager(connMgr) Cache = NewCacheS(cfg, dm, nil) if _, err := dm.GetDispatcherHost(dH.Tenant, dH.ID, true, true, utils.NonTransactional); err == nil { t.Error(err) } } func TestChargerProfileRemote(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.CacheChargerProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetDispatcherHost: func(ctx *context.Context, args, reply any) error { chrgPrflApiOpts, cancast := args.(ChargerProfileWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetChargerProfileDrv(chrgPrflApiOpts.ChargerProfile) return nil }, utils.ReplicatorSv1RemoveChargerProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveChargerProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) chrPrf := &ChargerProfile{ Tenant: "cgrates.org", ID: "CPP_3", FilterIDs: []string{"FLTR_CP_3"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), }, RunID: "*rated", AttributeIDs: []string{"ATTR_1"}, Weight: 20, } if err := dm.SetChargerProfile(chrPrf, false); err != nil { t.Error(err) } if val, err := dm.GetChargerProfile(chrPrf.Tenant, chrPrf.ID, true, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(chrPrf, val) { t.Errorf("expected %v,received %v", utils.ToJSON(val), utils.ToJSON(chrPrf)) } if err = dm.RemoveChargerProfile(chrPrf.Tenant, chrPrf.ID, false); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheChargerProfiles, chrPrf.TenantID()); has { t.Error("should been removed from the cache") } } func TestDispatcherProfileRemote(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.CacheDispatcherProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetDispatcherProfile: func(ctx *context.Context, args, reply any) error { dspApiOpts, cancast := args.(DispatcherProfileWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetDispatcherProfileDrv(dspApiOpts.DispatcherProfile) return nil }, utils.ReplicatorSv1RemoveDispatcherProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveDispatcherProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) dsp := &DispatcherProfile{ Tenant: "cgrates.org", ID: "Dsp1", FilterIDs: []string{"*string:~*req.Account:1001"}, Subsystems: []string{utils.MetaAny}, Strategy: utils.MetaFirst, Weight: 20, } if err := dm.SetDispatcherProfile(dsp, false); err != nil { t.Error(err) } if val, err := dm.GetDispatcherProfile(dsp.Tenant, dsp.ID, true, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, dsp) { t.Errorf("expected %v,received %v", utils.ToJSON(dsp), utils.ToJSON(val)) } if err := dm.RemoveDispatcherProfile(dsp.Tenant, dsp.ID, false); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheDispatcherProfiles, dsp.TenantID()); has { t.Error("should been removed from the cache") } } func TestRouteProfileRemote(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.CacheRouteProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetRouteProfile: func(ctx *context.Context, args, reply any) error { routeApiOpts, cancast := args.(RouteProfileWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetRouteProfileDrv(routeApiOpts.RouteProfile) return nil }, utils.ReplicatorSv1RemoveRouteProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveRouteProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) rpp := &RouteProfile{ Tenant: "cgrates.org", ID: "ROUTE_ACNT_1002", FilterIDs: []string{"FLTR_ACNT_1002"}, } if err := dm.SetRouteProfile(rpp, false); err != nil { t.Error(err) } if val, err := dm.GetRouteProfile(rpp.Tenant, rpp.ID, true, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, rpp) { t.Errorf("expected %v,received %v", utils.ToJSON(rpp), utils.ToJSON(val)) } if err := dm.RemoveRouteProfile(rpp.Tenant, rpp.ID, false); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheRouteProfiles, rpp.TenantID()); has { t.Error("should been removed from the cache") } } func TestRatingPlanRemote(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.CacheRatingPlans: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetRatingPlan: func(ctx *context.Context, args, reply any) error { rPnApiOpts, cancast := args.(RatingPlanWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetRatingPlanDrv(rPnApiOpts.RatingPlan) return nil }, utils.ReplicatorSv1RemoveRatingPlan: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveRatingPlanDrv(strApiOpts.Arg) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) rP := &RatingPlan{ Id: "RP1", Timings: map[string]*RITiming{ "30eab300": { Years: utils.Years{}, Months: utils.Months{}, MonthDays: utils.MonthDays{}, WeekDays: utils.WeekDays{}, StartTime: "00:00:00", }, }, } if err := dm.SetRatingPlan(rP); err != nil { t.Error(err) } if val, err := dm.GetRatingPlan(rP.Id, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, rP) { t.Errorf("expected %v,received %v", utils.ToJSON(rP), utils.ToJSON(val)) } if err = dm.RemoveRatingPlan(rP.Id, utils.NonTransactional); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheRatingPlans, rP.Id); has { t.Error("should been removed from the caches") } } func TestGetResourceRemote(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetDataStorage(tmpDm) SetConnManager(tmpConn) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheResources].Replicate = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheResources: { Limit: 3, Replicate: true, Remote: true, }, } rS := &Resource{ Tenant: "cgrates.org", ID: "ResGroup3", Usages: map[string]*ResourceUsage{ "651a8db2-4f67-4cf8-b622-169e8a482e21": { Tenant: "cgrates.org", ID: "651a8db2-4f67-4cf8-b622-169e8a482e21", Units: 2, }, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetResource: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(*utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetResourceDrv(tntApiOpts.Tenant, tntApiOpts.ID) *reply.(**Resource) = rS return nil }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if val, err := dm.GetResource(rS.Tenant, rS.ID, false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(rS, val) { t.Errorf("expected %v,received %v", utils.ToJSON(rS), utils.ToJSON(val)) } Cache = NewCacheS(cfg, dm, nil) SetConnManager(connMgr) if _, err := dm.GetResource(rS.Tenant, rS.ID, false, true, utils.NonTransactional); err == nil || err.Error() != "Can't Replicate" { t.Error(err) } } func TestGetResourceProfileRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheResourceProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } rsP := &ResourceProfile{ ID: "RES_ULTIMITED2", UsageTTL: time.Nanosecond, Limit: 10, AllocationMessage: "MessageAllocation", Blocker: true, Stored: true, Weight: 20, ThresholdIDs: []string{"Val1"}, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetResourceProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(*utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetResourceProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) *reply.(**ResourceProfile) = rsP return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if val, err := dm.GetResourceProfile(rsP.Tenant, rsP.ID, false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, rsP) { t.Errorf("expected %v,received %v", utils.ToJSON(rsP), utils.ToJSON(val)) } } func TestGetActionTriggers(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RplFiltered = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.CacheCfg().Partitions[utils.CacheActionTriggers].Replicate = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheActionTriggers: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } aT := ActionTriggers{ &ActionTrigger{ ID: "Test", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetActionTriggers: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetActionTriggersDrv(strApiOpts.Arg) *reply.(*ActionTriggers) = aT return nil }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) Cache.Set(utils.CacheActionTriggers, "Test", ActionTriggers{}, []string{}, false, utils.NonTransactional) if val, err := dm.GetActionTriggers(aT[0].ID, false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, aT) { t.Errorf("Expected %v,Received %v", utils.ToJSON(aT), utils.ToJSON(val)) } SetConnManager(connMgr) Cache = NewCacheS(cfg, dm, nil) if _, err := dm.GetActionTriggers(aT[0].ID, false, utils.NonTransactional); err == nil { t.Error(err) } } func TestGetActionTriggersErr(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RplFiltered = true cfg.CacheCfg().Partitions[utils.CacheActionTriggers].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheActionTriggers: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } aT := ActionTriggers{ &ActionTrigger{ ID: "Test", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetActionTriggers: func(ctx *context.Context, args, reply any) error { return utils.ErrNotFound }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr1 := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr1) SetDataStorage(dm) if _, err := dm.GetActionTriggers(aT[0].ID, true, utils.NonTransactional); err == nil { t.Error(err) } Cache.Set(utils.CacheActionTriggers, "Test", nil, []string{}, false, utils.NonTransactional) if _, err := dm.GetActionTriggers(aT[0].ID, false, utils.NonTransactional); err == nil || err != utils.ErrNotFound { t.Error(err) } SetConnManager(connMgr1) Cache = NewCacheS(cfg, dm, nil) if _, err := dm.GetActionTriggers(aT[0].ID, true, utils.NonTransactional); err == nil || err.Error() != "Can't Replicate" { t.Error(err) } var dm2 *DataManager if _, err = dm2.GetActionTriggers("test", false, utils.NonTransactional); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestGetSharedGroupRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheSharedGroups: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } shG := &SharedGroup{ Id: "testID", AccountParameters: map[string]*SharingParameters{ "string1": { Strategy: "strategyTEST1", RatingSubject: "RatingSubjectTEST1", }, "string2": { Strategy: "strategyTEST2", RatingSubject: "RatingSubjectTEST2", }, }, MemberIds: utils.StringMap{ "string1": true, "string2": false, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetSharedGroup: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetSharedGroupDrv(strApiOpts.Arg) *reply.(**SharedGroup) = shG return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if val, err := dm.GetSharedGroup(shG.Id, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, shG) { t.Errorf("expected %v,received %v", utils.ToJSON(shG), utils.ToJSON(val)) } } func TestGetStatQueueProfileRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheStatQueueProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } sqP := &StatQueueProfile{ Tenant: "cgrates.org", ID: "SQ_ID", FilterIDs: []string{"FLTR_ID"}, Weight: 10, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetStatQueueProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(*utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetStatQueueProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) *reply.(**StatQueueProfile) = sqP return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if val, err := dm.GetStatQueueProfile(sqP.Tenant, sqP.ID, true, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, sqP) { t.Errorf("expected %v,received %v", utils.ToJSON(sqP), utils.ToJSON(val)) } } func TestStatQueueProfileRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} cfg.DataDbCfg().RplConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheStatQueueProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, utils.CacheStatQueues: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } sqP := &StatQueueProfile{ Tenant: "cgrates.org", ID: "SQ_ID", FilterIDs: []string{"FLTR_ID"}, Weight: 10, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetStatQueueProfile: func(ctx *context.Context, args, reply any) error { sqPApiOpts, cancast := args.(StatQueueProfileWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetStatQueueProfileDrv(sqPApiOpts.StatQueueProfile) return nil }, utils.ReplicatorSv1SetStatQueue: func(ctx *context.Context, args, reply any) error { sqApiOpts, cancast := args.(StatQueueWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetStatQueueDrv(nil, sqApiOpts.StatQueue) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) Cache.Set(utils.CacheStatQueueProfiles, utils.ConcatenatedKey(sqP.Tenant, sqP.ID), &StatQueueProfile{ QueueLength: 2, }, []string{}, true, utils.NonTransactional) if err := dm.SetStatQueueProfile(sqP, false); err != nil { t.Error(err) } } func TestDMActionsRemote(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.MetaReplicator)} cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheActions: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetActions: func(ctx *context.Context, args, reply any) error { sArgApiOpts, cancast := args.(SetActionsArgsWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetActionsDrv(sArgApiOpts.Key, sArgApiOpts.Acs) return nil }, utils.ReplicatorSv1GetActions: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetActionsDrv(strApiOpts.Arg) return nil }, utils.ReplicatorSv1RemoveActions: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveActionsDrv(strApiOpts.Arg) return nil }, }} acs := Actions{{ Id: "SHARED", ActionType: utils.MetaTopUp, ExpirationString: utils.MetaUnlimited}} db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err := dm.SetActions("KeyActions", acs); err != nil { t.Error(err) } Cache.Set(utils.CacheActions, "KeyActions", acs, []string{}, true, utils.NonTransactional) if val, err := dm.GetActions("KeyActions", false, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(acs, val) { t.Errorf("expected %+v,received %+v", utils.ToJSON(acs), utils.ToJSON(val)) } if err := dm.RemoveActions("KeyActions"); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheActions, "KeyActions"); has { t.Error("shouln't be in db cache") } } func TestGetDispatcherHost(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RmtConnID = "rmt" cfg.GeneralCfg().NodeID = "node" cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheDispatcherHosts: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } dh := &DispatcherHost{ Tenant: "cgrates.org:HostID", RemoteHost: &config.RemoteHost{ ID: "Host1", Address: "127.0.0.1:2012", TLS: true, Transport: utils.MetaJSON, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetDispatcherHost: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(*utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetDispatcherHostDrv(tntApiOpts.Tenant, tntApiOpts.ID) *reply.(**DispatcherHost) = dh return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if val, err := dm.GetDispatcherHost("cgrates.org", "HostID", false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(dh, val) { t.Errorf("expected %v,received %v", utils.ToJSON(val), utils.ToJSON(dh)) } } func TestGetReverseDestinationRemote(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp connMgr = tmpConn SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.CacheCfg().Partitions[utils.CacheReverseDestinations].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().RmtConnID = "rmt" cfg.GeneralCfg().NodeID = "node" cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheReverseDestinations: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } ids := []string{"dest1", "dest2"} clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetReverseDestination: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetReverseDestinationDrv(strApiOpts.Arg, utils.NonTransactional) *reply.(*[]string) = ids return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if val, err := dm.GetReverseDestination("CRUDReverseDestination", false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, ids) { t.Errorf("expected %v,received %v", utils.ToJSON(ids), utils.ToJSON(val)) } Cache = NewCacheS(cfg, dm, nil) clientConn2 := make(chan birpc.ClientConnector, 1) clientConn2 <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate") }, }, } connMgr2 := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn2, }) SetConnManager(connMgr2) if _, err := dm.GetReverseDestination("CRUDReverseDestination", false, true, utils.NonTransactional); err == nil || err.Error() != "Can't replicate" { t.Error(err) } var dm2 *DataManager if _, err := dm2.GetReverseDestination("CRUDReverseDestination", false, true, utils.NonTransactional); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestDMRemoveDestination(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetDataStorage(tmpDm) connMgr = tmpConn }() Cache.Clear(nil) cfg.DataDbCfg().RplConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RplFiltered = true cfg.CacheCfg().Partitions[utils.CacheDestinations].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheDestinations: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, utils.CacheReverseDestinations: { Remote: true, }, } dest := &Destination{ Id: "nat", Prefixes: []string{"0257", "0256", "0723"}, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1RemoveDestination: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveDestinationDrv(strApiOpts.Arg, utils.NonTransactional) return nil }, utils.ReplicatorSv1GetReverseDestination: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetReverseDestinationDrv(strApiOpts.Arg, utils.NonTransactional) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) dm.DataDB().SetDestinationDrv(dest, utils.NonTransactional) if err := dm.RemoveDestination(dest.Id, utils.NonTransactional); err != nil { t.Error(err) } if err := dm.RemoveDestination(dest.Id, utils.NonTransactional); err == nil || err != utils.ErrNotFound { t.Error(err) } Cache = NewCacheS(cfg, dm, nil) clientConn2 := make(chan birpc.ClientConnector, 1) clientConn2 <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.CacheSv1ReplicateRemove: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate") }, }, } connMgr2 := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn2, }) SetConnManager(connMgr2) if err := dm.RemoveDestination(dest.Id, utils.NonTransactional); err == nil { t.Error(err) } var dm2 *DataManager if err := dm2.RemoveDestination(dest.Id, utils.NonTransactional); err == nil { t.Error(err) } } func TestDMRemoveFilter(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheFilters: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: false, }, utils.CacheReverseFilterIndexes: { Remote: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1RemoveFilter: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.RemoveFilterDrv(tntApiOpts.TenantID.Tenant, tntApiOpts.TenantID.ID) return nil }, utils.ReplicatorSv1GetIndexes: func(ctx *context.Context, args, reply any) error { return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) fltr := &Filter{ Tenant: "cgrates.org", ID: "Filter1", Rules: []*FilterRule{ { Element: "~*req.Account", Type: utils.MetaString, Values: []string{"1001", "1002"}, }, }, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), }, } dm.DataDB().SetFilterDrv(fltr) if err := dm.RemoveFilter(fltr.Tenant, fltr.ID, true); err == nil { t.Error(err) } if err := dm.RemoveFilter(fltr.Tenant, fltr.ID, false); err != nil { t.Error(err) } if err := dm.RemoveFilter(fltr.Tenant, fltr.ID, false); err == nil || err != utils.ErrNotFound { t.Error(err) } var dm2 *DataManager if err := dm2.RemoveFilter(fltr.Tenant, fltr.ID, false); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestRemoveStatQueueProfile(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheStatQueueProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, utils.CacheStatQueues: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, utils.CacheReverseFilterIndexes: { Remote: true, }, } sQ := &StatQueueProfile{ Tenant: "cgrates.org", ID: "STATS_RES_TEST12", FilterIDs: []string{"FLTR_ST_Resource1", "*string:~*req.Account:1001"}, Weight: 50, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1RemoveStatQueueProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemStatQueueProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) return nil }, utils.ReplicatorSv1GetIndexes: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) dm.DataDB().SetStatQueueProfileDrv(sQ) if err = dm.RemoveStatQueueProfile(sQ.Tenant, sQ.ID, true); err == nil { t.Error(err) } dm.DataDB().SetStatQueueProfileDrv(sQ) if err = dm.RemoveStatQueueProfile(sQ.Tenant, sQ.ID, false); err != nil { t.Error(err) } if err = dm.RemoveStatQueueProfile(sQ.Tenant, sQ.ID, true); err == nil || err != utils.ErrNotFound { t.Error(err) } var dm2 *DataManager if err = dm2.RemoveStatQueueProfile(sQ.Tenant, sQ.ID, true); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestDMGetTimingRemote(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheTimings].Replicate = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().RmtConnID = "rmt" cfg.GeneralCfg().NodeID = "node" cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheTimings: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } tp := &utils.TPTiming{ ID: "MIDNIGHT", Years: utils.Years{2020, 2019}, Months: utils.Months{1, 2, 3, 4}, MonthDays: utils.MonthDays{5, 6, 7, 8}, WeekDays: utils.WeekDays{0, 1, 2, 3}, StartTime: "00:00:00", EndTime: "00:00:01", } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetTiming: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetTimingDrv(strApiOpts.Arg) *reply.(**utils.TPTiming) = tp return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if _, err := dm.GetTiming(tp.ID, true, utils.NonTransactional); err != nil { t.Error(err) } Cache = NewCacheS(cfg, dm, nil) clientConn2 := make(chan birpc.ClientConnector, 1) clientConn2 <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate") }, }, } connMgr2 := NewConnManager(cfg, map[string]chan birpc.ClientConnector{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn2}) SetConnManager(connMgr2) if _, err := dm.GetTiming(tp.ID, true, utils.NonTransactional); err == nil || err.Error() != "Can't replicate" { t.Error(err) } var dm2 *DataManager if _, err := dm2.GetTiming(tp.ID, true, utils.NonTransactional); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestDmGetActions(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheTimings].Replicate = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RmtConnID = "rmt" cfg.GeneralCfg().NodeID = "node" cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheActions: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } acs := &Actions{ {Id: "MINI", ActionType: utils.MetaTopUpReset, ExpirationString: utils.MetaUnlimited}, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetActions: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetActionsDrv(strApiOpts.Arg) *reply.(*Actions) = *acs return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if _, err := dm.GetActions("MINI", true, utils.NonTransactional); err != nil { t.Error(err) } } func TestDMSetLoadIDs(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheTimings].Replicate = true cfg.DataDbCfg().RplConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheLoadIDs: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetLoadIDs: func(ctx *context.Context, args, reply any) error { ldApiOpts, cancast := args.(*utils.LoadIDsWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetLoadIDsDrv(ldApiOpts.LoadIDs) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) ld := map[string]int64{ "load1": 23, "load2": 22, } if err := dm.SetLoadIDs(ld); err != nil { t.Error(err) } dm.dataDB = &DataDBMock{} if err = dm.SetLoadIDs(ld); err == nil || err != utils.ErrNotImplemented { t.Error(err) } var dm2 *DataManager if err = dm2.SetLoadIDs(ld); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestGetItemLoadIDsRemote(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheLoadIDs].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.CacheCfg().Partitions[utils.CacheLoadIDs].Remote = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheLoadIDs: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } ld := map[string]int64{ "load1": 23, "load2": 22, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetItemLoadIDs: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } *reply.(*map[string]int64) = ld dm.DataDB().GetItemLoadIDsDrv(strApiOpts.Arg) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if val, err := dm.GetItemLoadIDs("load1", true); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, ld) { t.Error(err) } for key := range ld { if _, has := Cache.Get(utils.CacheLoadIDs, key); !has { t.Error("Item isn't stored on the Cache") } } Cache = NewCacheS(cfg, dm, nil) clientconn := make(chan birpc.ClientConnector, 1) clientconn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate") }, }, } connMgr2 := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientconn, }) SetConnManager(connMgr2) if _, err := dm.GetItemLoadIDs("load1", true); err == nil { t.Error(err) } } func TestDMItemLoadIDsRemoteErr(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheLoadIDs].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.CacheCfg().Partitions[utils.CacheLoadIDs].Remote = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheLoadIDs: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", }, } ld := map[string]int64{ "load1": 23, "load2": 22, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetItemLoadIDs: func(ctx *context.Context, args, reply any) error { *reply.(*map[string]int64) = ld return utils.ErrNotFound }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetConnManager(connMgr) Cache = NewCacheS(cfg, dm, nil) if _, err := dm.GetItemLoadIDs("load1", true); err == nil || err.Error() != "Can't replicate" { t.Error(err) } } func TestActionPlanRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheActionPlans: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } actPln := &ActionPlan{ Id: "TestActionPlansRemoveMember1", AccountIDs: utils.StringMap{"one": true}, ActionTimings: []*ActionTiming{ { Uuid: "uuid1", Timing: &RateInterval{ Timing: &RITiming{ Years: utils.Years{2012}, Months: utils.Months{}, MonthDays: utils.MonthDays{}, WeekDays: utils.WeekDays{}, StartTime: utils.MetaASAP, }, }, Weight: 10, ActionsID: "MINI", }, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetActionPlan: func(ctx *context.Context, args, reply any) error { setActPlnOpts, cancast := args.(*SetActionPlanArgWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetActionPlanDrv(setActPlnOpts.Key, setActPlnOpts.Ats) return nil }, utils.ReplicatorSv1RemoveActionPlan: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveActionPlanDrv(strApiOpts.Arg) return nil }, utils.ReplicatorSv1GetAllActionPlans: func(ctx *context.Context, args, reply any) error { *reply.(*map[string]*ActionPlan) = map[string]*ActionPlan{ "act_key": actPln, } return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err := dm.SetActionPlan("act_key", actPln, true, utils.NonTransactional); err != nil { t.Error(err) } if err := dm.RemoveActionPlan("act_key", utils.NonTransactional); err != nil { t.Error(err) } exp := map[string]*ActionPlan{ "act_key": actPln, } if val, err := dm.GetAllActionPlans(); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, exp) { t.Errorf("expected %v,received %v", utils.ToJSON(exp), utils.ToJSON(val)) } } func TestAccountActionPlansRemote(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheAccountActionPlans: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetAccountActionPlans: func(ctx *context.Context, args, reply any) error { setActPlnOpts, cancast := args.(*SetActionPlanArgWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetActionPlanDrv(setActPlnOpts.Key, setActPlnOpts.Ats) return nil }, utils.ReplicatorSv1RemAccountActionPlans: func(ctx *context.Context, args, reply any) error { return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err := dm.SetAccountActionPlans("acc_ID", []string{"act_pln", "act_pln"}, true); err != nil { t.Error(err) } if err = dm.RemAccountActionPlans("acc_ID", []string{}); err != nil { t.Error(err) } } func TestComputeIndexes(t *testing.T) { cfg := config.NewDefaultCGRConfig() data, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(data, cfg.CacheCfg(), nil) thd := &ThresholdProfile{ Tenant: "cgrates.org", ID: "THD_2", FilterIDs: []string{"*string:~*req.Account:1001"}, MinHits: 0, Async: true, } dm.SetThresholdProfile(thd, false) transactionID := utils.GenUUID() if _, err := ComputeIndexes(dm, "cgrates.org", utils.EmptyString, utils.CacheThresholdFilterIndexes, nil, transactionID, func(tnt, id, grp string) (*[]string, error) { th, e := dm.GetThresholdProfile(tnt, id, true, false, utils.NonTransactional) if e != nil { return nil, e } return utils.SliceStringPointer(slices.Clone(th.FilterIDs)), nil }, nil); err != nil { t.Error(err) } } func TestUpdateFilterIndexRouteIndex(t *testing.T) { tmp := Cache defer func() { Cache = tmp }() Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() dataDB, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(dataDB, cfg.CacheCfg(), nil) oldFlt := &Filter{ Tenant: "cgrates.org", ID: "fltr_test", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Cost", Values: []string{"unRegVal2"}, }, }, } if err := oldFlt.Compile(); err != nil { t.Error(err) } if err := dm.SetFilter(oldFlt, true); err != nil { t.Error(err) } rp := &RouteProfile{ Tenant: "cgrates.org", ID: "ID", FilterIDs: []string{"fltr_test"}, Sorting: utils.MetaQOS, SortingParameters: []string{"param"}, Routes: []*Route{{ ID: "RT1", FilterIDs: []string{"fltr1"}, AccountIDs: []string{"acc1"}, ResourceIDs: []string{"res1"}, StatIDs: []string{"stat1"}, RouteParameters: "params", }}, } if err := dm.SetRouteProfile(rp, true); err != nil { t.Error(err) } expindx := map[string]utils.StringSet{ "*string:*req.Cost:unRegVal2": {"ID": {}}, } getindx, err := dm.GetIndexes(utils.CacheRouteFilterIndexes, cfg.GeneralCfg().DefaultTenant, true, true) if err != nil { t.Error(err) } else if !reflect.DeepEqual(expindx, getindx) { t.Errorf("Expected %v, Received %v", utils.ToJSON(expindx), utils.ToJSON(getindx)) } newFlt := &Filter{ Tenant: "cgrates.org", ID: "fltr_test", Rules: []*FilterRule{ { Type: utils.MetaPrefix, Element: "~*req.Usage", Values: []string{"10s"}, }, }, } if err := newFlt.Compile(); err != nil { t.Error(err) } if err := dm.SetFilter(newFlt, false); err != nil { t.Error(err) } if err := UpdateFilterIndex(dm, oldFlt, newFlt); err != nil { t.Error(err) } expindxNew := map[string]utils.StringSet{ "*prefix:*req.Usage:10s": {"ID": {}}, } getindxNew, err := dm.GetIndexes(utils.CacheRouteFilterIndexes, cfg.GeneralCfg().DefaultTenant, true, true) if err != nil { t.Error(err) } else if !reflect.DeepEqual(expindxNew, getindxNew) { t.Errorf("Expected %v, Received %v", utils.ToJSON(expindxNew), utils.ToJSON(getindxNew)) } } func TestUpdateFilterIndexStatIndex(t *testing.T) { tmp := Cache defer func() { Cache = tmp }() Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() dataDB, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(dataDB, cfg.CacheCfg(), nil) oldFlt := &Filter{ Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, ID: "FLTR_STATS_1", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Stats", Values: []string{"StatQueueProfile1"}, }, }, } if err := oldFlt.Compile(); err != nil { t.Error(err) } if err := dm.SetFilter(oldFlt, true); err != nil { t.Error(err) } sQ := &StatQueueProfile{ Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, ID: "TEST_PROFILE1", ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2020, 4, 18, 14, 25, 0, 0, time.UTC), ExpiryTime: time.Date(2020, 4, 18, 14, 25, 0, 0, time.UTC), }, QueueLength: 10, TTL: 10 * time.Second, Metrics: []*MetricWithFilters{ { MetricID: "*sum", }, { MetricID: "*acd", }, }, ThresholdIDs: []string{"Val1", "Val2"}, Blocker: true, Stored: true, Weight: 20, MinItems: 1, FilterIDs: []string{"FLTR_STATS_1"}, } if err := dm.SetStatQueueProfile(sQ, true); err != nil { t.Error(err) } expindx := map[string]utils.StringSet{ "*string:*req.Stats:StatQueueProfile1": {"TEST_PROFILE1": {}}, } if getindx, err := dm.GetIndexes(utils.CacheStatFilterIndexes, cfg.GeneralCfg().DefaultTenant, true, true); err != nil { t.Error(err) } else if !reflect.DeepEqual(expindx, getindx) { t.Errorf("Expected %v, Received %v", utils.ToJSON(expindx), utils.ToJSON(getindx)) } newFlt := &Filter{ Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, ID: "FLTR_STATS_1", Rules: []*FilterRule{ { Type: utils.MetaPrefix, Element: "~*req.Usage", Values: []string{"10s"}, }, }, } if err := newFlt.Compile(); err != nil { t.Error(err) } if err := dm.SetFilter(newFlt, false); err != nil { t.Error(err) } if err := UpdateFilterIndex(dm, oldFlt, newFlt); err != nil { t.Error(err) } expindxNew := map[string]utils.StringSet{ "*prefix:*req.Usage:10s": {"TEST_PROFILE1": {}}, } if getindx, err := dm.GetIndexes(utils.CacheStatFilterIndexes, cfg.GeneralCfg().DefaultTenant, true, true); err != nil { t.Error(err) } else if !reflect.DeepEqual(expindxNew, getindx) { t.Errorf("Expected %v, Received %v", utils.ToJSON(expindx), utils.ToJSON(getindx)) } } func TestDMRatingProfile(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RplFiltered = true cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheRatingProfiles: { Limit: 3, Replicate: true, APIKey: "key", RouteID: "route", Remote: true, }, } rpf := &RatingProfile{ Id: "*out:TCDDBSWF:call:*any", RatingPlanActivations: RatingPlanActivations{&RatingPlanActivation{ ActivationTime: time.Date(2015, 01, 01, 8, 0, 0, 0, time.UTC), RatingPlanId: "RP_ANY2CNT", }}, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetRatingProfile: func(ctx *context.Context, args, reply any) error { rtPrfApiOpts, cancast := args.(*RatingProfileWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.dataDB.SetRatingProfileDrv(rtPrfApiOpts.RatingProfile) return nil }, utils.ReplicatorSv1RemoveRatingProfile: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveRatingProfileDrv(strApiOpts.Arg) return nil }, utils.ReplicatorSv1GetRatingProfile: func(ctx *context.Context, args, reply any) error { strApiOpts, cancast := args.(*utils.StringWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().GetRatingProfileDrv(strApiOpts.Arg) *reply.(**RatingProfile) = rpf return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err := dm.SetRatingProfile(rpf); err != nil { t.Error(err) } if err := dm.RemoveRatingProfile(rpf.Id); err != nil { t.Error(err) } if _, err := dm.GetRatingProfile(rpf.Id, true, utils.NonTransactional); err != nil { t.Error(err) } } func TestUpdateFilterDispatcherIndex(t *testing.T) { tmp := Cache tmpDm := dm defer func() { Cache = tmp dm = tmpDm config.SetCgrConfig(config.NewDefaultCGRConfig()) }() Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() dataDB, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(dataDB, cfg.CacheCfg(), nil) oldFlt := &Filter{ Tenant: "cgrates.org", ID: "DISPATCHER_FLTR1", Rules: []*FilterRule{{Type: utils.MetaString, Element: "~*req.Destination", Values: []string{"ACC1", "ACC2", "~*req.Account"}}}, } if err := oldFlt.Compile(); err != nil { t.Error(err) } if err := dm.SetFilter(oldFlt, true); err != nil { t.Error(err) } disp := &DispatcherProfile{ Tenant: "cgrates.org", ID: "Dsp", Subsystems: []string{"*any"}, FilterIDs: []string{"DISPATCHER_FLTR1"}, Strategy: utils.MetaFirst, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), }, StrategyParams: map[string]any{}, Weight: 20, } if err := dm.SetDispatcherProfile(disp, true); err != nil { t.Error(err) } exp := map[string]utils.StringSet{ "*string:*req.Destination:ACC1": {"Dsp": {}}, "*string:*req.Destination:ACC2": {"Dsp": {}}, } if indx, err := dm.GetIndexes(utils.CacheDispatcherFilterIndexes, "cgrates.org:*any", true, true); err != nil { t.Error(err) } else if !reflect.DeepEqual(exp, indx) { t.Errorf("Expected %v, Received %v", utils.ToJSON(exp), utils.ToJSON(indx)) } newFlt := &Filter{ Tenant: "cgrates.org", ID: "DISPATCHER_FLTR1", Rules: []*FilterRule{{ Type: utils.MetaString, Element: "~*req.Charger", Values: []string{"ChargerProfile2"}}}, } if err := newFlt.Compile(); err != nil { t.Error(err) } if err := dm.SetFilter(newFlt, true); err != nil { t.Error(err) } exp = map[string]utils.StringSet{ "*string:*req.Charger:ChargerProfile2": {"Dsp": {}}, } if indx, err := dm.GetIndexes(utils.CacheDispatcherFilterIndexes, "cgrates.org:*any", true, true); err != nil { t.Error(err) } else if !reflect.DeepEqual(exp, indx) { t.Errorf("Expected %v, Received %v", utils.ToJSON(exp), utils.ToJSON(indx)) } } func TestDMGetRatingPlan(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheLoadIDs].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.CacheCfg().Partitions[utils.CacheRatingPlans].Remote = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheRatingPlans: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } rpL := &RatingPlan{ Id: "id", DestinationRates: map[string]RPRateList{ "DestinationRates": {&RPRate{Rating: "Rating"}}}, Ratings: map[string]*RIRate{"Ratings": {ConnectFee: 0.7}}, Timings: map[string]*RITiming{"Timings": {Months: utils.Months{4}}}, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetRatingPlan: func(ctx *context.Context, args, reply any) error { *reply.(**RatingPlan) = rpL return nil }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate ") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if _, err := dm.GetRatingPlan("id", true, utils.NonTransactional); err != nil { t.Error(err) } } func TestDMChargerProfile(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheLoadIDs].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.CacheCfg().Partitions[utils.CacheRatingPlans].Remote = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheChargerProfiles: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } chP := &ChargerProfile{ Tenant: "cgrates.org", ID: "CPP_3", FilterIDs: []string{"FLTR_CP_3"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), }, RunID: "*rated", AttributeIDs: []string{"ATTR_1"}, Weight: 20, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetChargerProfile: func(ctx *context.Context, args, reply any) error { *reply.(**ChargerProfile) = chP return nil }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate ") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if _, err := dm.GetChargerProfile(chP.Tenant, chP.ID, false, true, utils.NonTransactional); err != nil { t.Error(err) } } func TestDMDispatcherProfile(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.CacheCfg().Partitions[utils.CacheLoadIDs].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.CacheCfg().Partitions[utils.CacheRatingPlans].Remote = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheDispatcherProfiles: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } dPP := &DispatcherProfile{ Tenant: cfg.GeneralCfg().DefaultTenant, ID: "Dsp", Subsystems: []string{"*any"}, FilterIDs: []string{"DISPATCHER_FLTR1"}, Strategy: utils.MetaFirst, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), }, StrategyParams: map[string]any{}, Weight: 20, Hosts: DispatcherHostProfiles{ &DispatcherHostProfile{ ID: "C1", FilterIDs: []string{}, Weight: 10, Params: map[string]any{"0": "192.168.54.203", utils.MetaRatio: "2"}, Blocker: false, }, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetDispatcherProfile: func(ctx *context.Context, args, reply any) error { *reply.(**DispatcherProfile) = dPP return nil }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't replicate ") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if _, err := dm.GetDispatcherProfile(dPP.Tenant, dPP.ID, false, true, utils.NonTransactional); err != nil { t.Error(err) } } func TestCacheDataFromDB(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetDataStorage(tmpDm) }() Cache.Clear(nil) db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(db, cfg.CacheCfg(), nil) if err := dm.CacheDataFromDB("INVALID", nil, false); err == nil || err.Error() != utils.UnsupportedCachePrefix { t.Error(err) } rp := &RatingPlan{ Id: "id", DestinationRates: map[string]RPRateList{ "DestinationRates": {&RPRate{Rating: "Rating"}}}, Ratings: map[string]*RIRate{"Ratings": {ConnectFee: 0.7}}, Timings: map[string]*RITiming{"Timings": {Months: utils.Months{4}}}, } if err := dm.SetRatingPlan(rp); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheRatingPlans, rp.Id); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.RatingPlanPrefix, []string{rp.Id}, false); err != nil { t.Error(err) } rP := &RatingProfile{ Id: "*out:TCDDBSWF:call:*any", RatingPlanActivations: RatingPlanActivations{&RatingPlanActivation{ ActivationTime: time.Date(2015, 01, 01, 8, 0, 0, 0, time.UTC), RatingPlanId: rp.Id, }}, } if err := dm.SetRatingProfile(rP); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheRatingProfiles, rP.Id); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.RatingProfilePrefix, []string{rP.Id}, false); err != nil { t.Error(err) } as := Actions{ &Action{ ActionType: utils.MetaSetBalance, Filters: []string{"*string:~*req.BalanceMap.*monetary[0].ID:*default", "*lt:~*req.BalanceMap.*monetary[0].Value:0"}, Balance: &BalanceFilter{ Type: utils.StringPointer("*sms"), ID: utils.StringPointer("for_v3hsillmilld500m_sms_ill"), Disabled: utils.BoolPointer(true), }, Weight: 9, }, } if err := dm.SetActions("test", as); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheActions, "test"); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.ActionPrefix, []string{"test"}, false); err != nil { t.Error(err) } rsPrf := &ResourceProfile{ Tenant: "tenant.custom", ID: "RES_GRP1", FilterIDs: []string{ "*string:~*req.RequestType:*rated", }, UsageTTL: 10 * time.Microsecond, Limit: 10, AllocationMessage: "MessageAllocation", Blocker: true, Stored: true, Weight: 20, } if err := dm.SetResourceProfile(rsPrf, false); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheResourceProfiles, "test"); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.ResourceProfilesPrefix, []string{utils.ConcatenatedKey(rsPrf.Tenant, rsPrf.ID)}, false); err != nil { t.Error(err) } ru1 := &ResourceUsage{ Tenant: "cgrates.org", ID: "RU1", ExpiryTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC), Units: 1, } rs := &Resource{ Tenant: "cgrates.org", ID: "RES_GRP1", rPrf: rsPrf, TTLIdx: []string{ru1.ID}, tUsage: utils.Float64Pointer(2), } if err = dm.SetResource(rs); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheResources, utils.ConcatenatedKey(rs.Tenant, rs.ID)); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.ResourcesPrefix, []string{utils.ConcatenatedKey(rs.Tenant, rs.ID)}, false); err != nil { t.Error(err) } if err := dm.CacheDataFromDB(utils.ResourceFilterIndexes, []string{"*resources:*string:~*req.RequestType:*rated"}, false); err != nil { t.Error(err) } sqPrf := &StatQueueProfile{ Tenant: "cgrates.org", ID: "SQ1", FilterIDs: []string{"*string:~*req.Account:1001"}, Weight: 50, } if err = dm.SetStatQueueProfile(sqPrf, false); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheStatQueueProfiles, utils.ConcatenatedKey(sqPrf.Tenant, sqPrf.ID)); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.StatQueueProfilePrefix, []string{utils.ConcatenatedKey(sqPrf.Tenant, sqPrf.ID)}, false); err != nil { t.Error(err) } if err := dm.CacheDataFromDB(utils.StatFilterIndexes, []string{"*statqueue_profiles:*string:~*req.Account:1001"}, false); err != nil { t.Error(err) } sq := &StatQueue{ sqPrfl: sqPrf, Tenant: "cgrates.org", ID: "SQ1", SQItems: []SQItem{ { EventID: "SqProcessEvent", }, }, SQMetrics: map[string]StatMetric{ utils.MetaTCD: &StatTCD{}, }, } if err = dm.SetStatQueue(sq); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheStatQueues, utils.ConcatenatedKey(sq.Tenant, sq.ID)); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.StatQueuePrefix, []string{utils.ConcatenatedKey(sq.Tenant, sq.ID)}, false); err != nil { t.Error(err) } thdPrf := &ThresholdProfile{ Tenant: "cgrates.org", ID: "TH1", FilterIDs: []string{"*string:~*req.Account:1001", "*notstring:~*req.Destination:+49123"}, } if err = dm.SetThresholdProfile(thdPrf, false); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheThresholdProfiles, utils.ConcatenatedKey(thdPrf.Tenant, thdPrf.ID)); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.ThresholdProfilePrefix, []string{utils.ConcatenatedKey(thdPrf.Tenant, thdPrf.ID)}, false); err != nil { t.Error(err) } if err := dm.CacheDataFromDB(utils.ThresholdFilterIndexes, []string{"*threshold_profiles:*string:~*req.Account:1001"}, false); err != nil { t.Error(err) } thd := &Threshold{ Tenant: "cgrates.org", ID: "TH1", tPrfl: thdPrf, } if err = dm.SetThreshold(thd); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheThresholds, utils.ConcatenatedKey(thd.Tenant, thd.ID)); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.ThresholdPrefix, []string{utils.ConcatenatedKey(thd.Tenant, thd.ID)}, false); err != nil { t.Error(err) } rPrf := &RouteProfile{ Tenant: "cgrates.org", ID: "SUP1", FilterIDs: []string{"*string:~*opts.Account:1001"}, Weight: 10, Sorting: utils.MetaQOS, SortingParameters: []string{}, Routes: []*Route{{ ID: "Sup", FilterIDs: []string{}, AccountIDs: []string{"1001"}, RatingPlanIDs: []string{"RT_PLAN1"}, ResourceIDs: []string{"RES1"}, Weight: 10, }}, } if err = dm.SetRouteProfile(rPrf, false); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheRouteProfiles, rPrf.TenantID()); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.RouteProfilePrefix, []string{rPrf.TenantID()}, false); err != nil { t.Error(err) } if err := dm.CacheDataFromDB(utils.RouteFilterIndexes, []string{"*route_profiles:*string:~*opts.Account:1001"}, false); err != nil { t.Error(err) } attrPrf := &AttributeProfile{ Tenant: "cgrates.org", ID: "1001", Contexts: []string{utils.MetaAny}, FilterIDs: []string{"*string:~*req.Account:1002"}, ActivationInterval: nil, Attributes: []*Attribute{ { Path: utils.MetaReq + utils.NestingSep + "Subject", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("call_1001", utils.InfieldSep), }, }, Blocker: false, Weight: 10, } if err = dm.SetAttributeProfile(attrPrf, false); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheAttributeProfiles, attrPrf.TenantID()); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.AttributeProfilePrefix, []string{attrPrf.TenantID()}, false); err != nil { t.Error(err) } if err := dm.CacheDataFromDB(utils.AttributeFilterIndexes, []string{"*attribute_profiles:*string:~*req.Account:1002"}, false); err != nil { t.Error(err) } chPrf := &ChargerProfile{ Tenant: "cgrates.com", ID: "CHRG_1", FilterIDs: []string{"*string:~*req.Account:1001"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), }, AttributeIDs: []string{"ATTR_1"}, Weight: 20, } if err = dm.SetChargerProfile(chPrf, false); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheChargerProfiles, chPrf.TenantID()); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.ChargerProfilePrefix, []string{chPrf.TenantID()}, false); err != nil { t.Error(err) } if err := dm.CacheDataFromDB(utils.ChargerFilterIndexes, []string{"*charger_profiles:*string:~*req.Account:1001"}, false); err != nil { t.Error(err) } dsPrf := &DispatcherProfile{ Tenant: "cgrates.org", ID: "Dsp1", FilterIDs: []string{"*string:~*req.Account:1001"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), }, Strategy: utils.MetaRandom, Weight: 20, } if err = dm.SetDispatcherProfile(dsPrf, false); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheDispatcherProfiles, dsPrf.TenantID()); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.DispatcherProfilePrefix, []string{dsPrf.TenantID()}, false); err != nil { t.Error(err) } if err := dm.CacheDataFromDB(utils.DispatcherFilterIndexes, []string{"*dispatcher_profiles:*string:~*req.Account:1001"}, false); err != nil { t.Error(err) } dH := &DispatcherHost{ Tenant: "cgrates.org", RemoteHost: &config.RemoteHost{ ID: "Host1", Address: "127.0.0.1:2012", Transport: utils.MetaJSON, }, } if err = dm.SetDispatcherHost(dH); err != nil { t.Error(err) } if _, hasIt := Cache.Get(utils.CacheDispatcherHosts, dH.TenantID()); hasIt { t.Error("Already in cache") } if err := dm.CacheDataFromDB(utils.DispatcherHostPrefix, []string{dH.TenantID()}, false); err != nil { t.Error(err) } if err := dm.CacheDataFromDB(utils.FilterIndexPrfx, []string{"*string:~*req.Account:1001:Dsp1"}, false); err != nil { t.Error(err) } } func TestCacheDataFromDBErr(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetDataStorage(tmpDm) SetConnManager(tmpConn) }() Cache.Clear(nil) cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.MetaThresholdProfiles: { Remote: true, }, } cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} cfg.CacheCfg().Partitions[utils.CacheThresholdProfiles].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetThresholdProfile: func(ctx *context.Context, args, reply any) error { return errors.New("Another Error") }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return fmt.Errorf("New Error") }, }, } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) Cache = NewCacheS(cfg, dm, nil) SetConnManager(connMgr) thdPrf := &ThresholdProfile{ Tenant: "cgrates.org", ID: "TH1", FilterIDs: []string{"*string:~*req.Account:1001", "*notstring:~*req.Destination:+49123"}, } if err := dm.CacheDataFromDB(utils.ThresholdProfilePrefix, []string{utils.ConcatenatedKey(thdPrf.Tenant, thdPrf.ID)}, false); err == nil { t.Error(err) } } func TestDMGetRouteProfile(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.CacheCfg().Partitions[utils.CacheRouteProfiles].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheRouteProfiles: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } rpL := &RouteProfile{Tenant: "cgrates.org", ID: "ROUTE_ACNT_1002", FilterIDs: []string{"FLTR_ACNT_1002"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2017, 11, 27, 00, 00, 00, 00, time.UTC), }, Sorting: utils.MetaLC, Routes: []*Route{ { ID: "route1", RatingPlanIDs: []string{"RP_1002_LOW"}, Weight: 10, Blocker: false, }, }, Weight: 10, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetRouteProfile: func(ctx *context.Context, args, reply any) error { *reply.(**RouteProfile) = rpL return nil }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if val, err := dm.GetRouteProfile(rpL.Tenant, rpL.ID, false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual(val, rpL) { t.Errorf("expected %v,received %v", utils.ToJSON(rpL), utils.ToJSON(val)) } Cache = NewCacheS(cfg, dm, nil) SetConnManager(connMgr) if _, err := dm.GetRouteProfile(rpL.Tenant, rpL.ID, false, true, utils.NonTransactional); err == nil { t.Error(err) } } func TestDMGetRouteProfileErr(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().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.CacheCfg().Partitions[utils.CacheRouteProfiles].Replicate = true cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheRouteProfiles: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetRouteProfile: func(ctx *context.Context, args, reply any) error { return utils.ErrNotFound }, utils.CacheSv1ReplicateSet: func(ctx *context.Context, args, reply any) error { return errors.New("Can't Replicate") }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) Cache = NewCacheS(cfg, dm, nil) SetConnManager(connMgr) if _, err := dm.GetRouteProfile("cgrates.org", "id", false, true, utils.NonTransactional); err == nil || err.Error() != "Can't Replicate" { t.Error(err) } Cache.Set(utils.CacheRouteProfiles, "cgrates.org:id", nil, []string{}, false, utils.NonTransactional) if _, err := dm.GetRouteProfile("cgrates.org", "id", true, true, utils.NonTransactional); err == nil || err != utils.ErrNotFound { t.Error(err) } var dm2 *DataManager if _, err := dm2.GetRouteProfile("cgrates.org", "id", false, true, utils.NonTransactional); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } } func TestUpdateFilterIndexStatErr1(t *testing.T) { tmp := Cache defer func() { Cache = tmp }() Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() dataDB, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(dataDB, cfg.CacheCfg(), nil) dm.dataDB = &DataDBMock{ GetIndexesDrvF: func(idxItmType, tntCtx string, idxKey ...string) (indexes map[string]utils.StringSet, err error) { return map[string]utils.StringSet{ utils.CacheStatFilterIndexes: { "ATTR_TEST": {}, }, }, nil }, } oldFlt := &Filter{ Tenant: "cgrates.org", ID: "fltr_test", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Cost", Values: []string{"unRegVal2"}, }, }, } newFlt := &Filter{ Tenant: "cgrates.org", ID: "fltr_test", Rules: []*FilterRule{ { Type: utils.MetaPrefix, Element: "~*req.Usage", Values: []string{"10s"}, }, }, } if err := UpdateFilterIndex(dm, oldFlt, newFlt); err != utils.ErrNotImplemented { t.Errorf("Expected error <%v>, Received error <%v>", utils.ErrNotImplemented, err) } } func TestUpdateFilterIndexRemoveThresholdErr1(t *testing.T) { tmp := Cache defer func() { Cache = tmp }() Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() dataDB, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(dataDB, cfg.CacheCfg(), nil) dm.dataDB = &DataDBMock{ GetIndexesDrvF: func(idxItmType, tntCtx string, idxKey ...string) (indexes map[string]utils.StringSet, err error) { return map[string]utils.StringSet{ utils.CacheThresholdFilterIndexes: { "ATTR_TEST": {}, }, }, nil }, } oldFlt := &Filter{ Tenant: "cgrates.org", ID: "fltr_test", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Cost", Values: []string{"unRegVal2"}, }, }, } newFlt := &Filter{ Tenant: "cgrates.org", ID: "fltr_test", Rules: []*FilterRule{ { Type: utils.MetaPrefix, Element: "~*req.Usage", Values: []string{"10s"}, }, }, } if err := UpdateFilterIndex(dm, oldFlt, newFlt); err != utils.ErrNotImplemented { t.Errorf("Expected error <%v>, Received error <%v>", utils.ErrNotImplemented, err) } } func TestDMAttributeProfile(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpDm := dm tmp := Cache tmpConn := connMgr defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmp SetConnManager(tmpConn) SetDataStorage(tmpDm) }() Cache.Clear(nil) cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().RplConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheAttributeProfiles: { Limit: 3, Remote: true, APIKey: "key", RouteID: "route", Replicate: true, }, } attrPrf := &AttributeProfile{ Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, ID: "ATTR_1001_SIMPLEAUTH", FilterIDs: []string{"*string:~*req.Account:1001"}, Contexts: []string{"simpleauth"}, Attributes: []*Attribute{ { FilterIDs: []string{}, Path: utils.MetaReq + utils.NestingSep + "Password", Type: utils.MetaConstant, Value: config.NewRSRParsersMustCompile("CGRateS.org", utils.InfieldSep), }, }, Weight: 20.0, } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetAttributeProfile: func(ctx *context.Context, args, reply any) error { *reply.(**AttributeProfile) = attrPrf return nil }, utils.ReplicatorSv1SetAttributeProfile: func(ctx *context.Context, args, reply any) error { attrPrfApiOpts, cancast := args.(*AttributeProfileWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetAttributeProfileDrv(attrPrfApiOpts.AttributeProfile) return nil }, utils.ReplicatorSv1RemoveAttributeProfile: func(ctx *context.Context, args, reply any) error { tntApiOpts, cancast := args.(*utils.TenantIDWithAPIOpts) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveAttributeProfileDrv(tntApiOpts.Tenant, tntApiOpts.ID) return nil }, }, } db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, }) config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) SetDataStorage(dm) if err := dm.SetAttributeProfile(attrPrf, false); err != nil { t.Error(err) } if err := dm.RemoveAttributeProfile(attrPrf.Tenant, attrPrf.ID, false); err != nil { t.Error(err) } if _, has := db.db.Get(utils.CacheAttributeProfiles, utils.ConcatenatedKey(attrPrf.Tenant, attrPrf.ID)); has { t.Error("Should been removed from db") } } func TestUpdateFilterResourceIndexErr(t *testing.T) { tmp := Cache defer func() { Cache = tmp }() Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() dataDB, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(dataDB, cfg.CacheCfg(), nil) dm.dataDB = &DataDBMock{ GetIndexesDrvF: func(idxItmType, tntCtx string, idxKey ...string) (indexes map[string]utils.StringSet, err error) { return map[string]utils.StringSet{ utils.CacheResourceFilterIndexes: { "ATTR_TEST": {}, }, }, nil }, } oldFlt := &Filter{ Tenant: "cgrates.org", ID: "RSC_FLTR1", Rules: []*FilterRule{{Type: utils.MetaString, Element: "~*req.Destination", Values: []string{"ACC1", "ACC2", "~*req.Account"}}}, } newFlt := &Filter{ Tenant: "cgrates.org", ID: "RSC_FLTR1", Rules: []*FilterRule{ { Element: "~*req.Account", Type: utils.MetaString, Values: []string{"1001", "1002"}, }, }} if err := UpdateFilterIndex(dm, oldFlt, newFlt); err != utils.ErrNotImplemented { t.Errorf("Expected error <%v>, Received error <%v>", utils.ErrNotImplemented, err) } } func TestUpdateFilterRouteIndexErr(t *testing.T) { tmp := Cache defer func() { Cache = tmp }() Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() dataDB, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(dataDB, cfg.CacheCfg(), nil) dm.dataDB = &DataDBMock{ GetIndexesDrvF: func(idxItmType, tntCtx string, idxKey ...string) (indexes map[string]utils.StringSet, err error) { return map[string]utils.StringSet{ utils.CacheRouteFilterIndexes: { "ATTR_TEST": {}, }, }, nil }, } oldFlt := &Filter{ Tenant: "cgrates.org", ID: "FLTR_SUPP_2", Rules: []*FilterRule{{ Type: utils.MetaString, Element: "~*req.Route", Values: []string{"RouteProfile2"}, }}, } newFlt := &Filter{ Tenant: "cgrates.org", ID: "FLTR_SUPP_2", Rules: []*FilterRule{ { Type: utils.MetaGreaterOrEqual, Element: "~*req.PddInterval", Values: []string{(time.Second).String()}, }, }} if err := UpdateFilterIndex(dm, oldFlt, newFlt); err != utils.ErrNotImplemented { t.Errorf("Expected error <%v>, Received error <%v>", utils.ErrNotImplemented, err) } } func TestUpdateFilterChargersIndexErr(t *testing.T) { tmp := Cache defer func() { Cache = tmp }() Cache.Clear(nil) cfg := config.NewDefaultCGRConfig() dataDB, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(dataDB, cfg.CacheCfg(), nil) dm.dataDB = &DataDBMock{ GetIndexesDrvF: func(idxItmType, tntCtx string, idxKey ...string) (indexes map[string]utils.StringSet, err error) { return map[string]utils.StringSet{ utils.CacheChargerFilterIndexes: { "ATTR_TEST": {}, }, }, nil }, } oldFlt := &Filter{ Tenant: "cgrates.org", ID: "FLTR_CP_2", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Charger", Values: []string{"ChargerProfile2"}, }, }} newFlt := &Filter{ Tenant: "cgrates.org", ID: "FLTR_CP_2", Rules: []*FilterRule{ { Type: utils.MetaGreaterOrEqual, Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.Weight, Values: []string{"200.00"}, }, }} if err := UpdateFilterIndex(dm, oldFlt, newFlt); err != utils.ErrNotImplemented { t.Errorf("Expected error <%v>, Received error <%v>", utils.ErrNotImplemented, err) } } func TestDmIndexes(t *testing.T) { cfg := config.NewDefaultCGRConfig() defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) }() cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheResourceFilterIndexes: { Replicate: true, }, } cfg.DataDbCfg().RplConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1SetIndexes: func(ctx *context.Context, args, reply any) error { setcastIndxArg, cancast := args.(*utils.SetIndexesArg) if !cancast { return utils.ErrNotConvertible } dm.DataDB().SetIndexesDrv(setcastIndxArg.IdxItmType, setcastIndxArg.TntCtx, setcastIndxArg.Indexes, true, utils.NonTransactional) return nil }, utils.ReplicatorSv1RemoveIndexes: func(ctx *context.Context, args, reply any) error { gIdxArg, cancast := args.(*utils.GetIndexesArg) if !cancast { return utils.ErrNotConvertible } dm.DataDB().RemoveIndexesDrv(gIdxArg.IdxItmType, gIdxArg.Tenant, gIdxArg.IdxKeys...) return nil }, }, } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) idxes := map[string]utils.StringSet{ "*string:Account:1001": { "RL1": struct{}{}, }, "*string:Account:1002": { "RL1": struct{}{}, "RL2": struct{}{}, }, utils.ConcatenatedKey(utils.MetaNone, utils.MetaAny, utils.MetaAny): { "RL4": struct{}{}, "RL5": struct{}{}, }, } if err := dm.SetIndexes(utils.CacheResourceFilterIndexes, "cgrates.org", idxes, false, utils.NonTransactional); err != nil { t.Error(err) } if err := dm.RemoveIndexes(utils.CacheResourceFilterIndexes, "cgrates.org"); err != nil { t.Error(err) } } func TestDmCheckFilters(t *testing.T) { cfg := config.NewDefaultCGRConfig() defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) }() cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.MetaFilters: { Remote: true, }, } cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetFilter: func(ctx *context.Context, args, reply any) error { fltr := &Filter{ ID: "FLTR_1", Tenant: "cgrates.org", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Account", Values: []string{"1001", "1002"}, }, }, } *reply.(*Filter) = *fltr return nil }, }, } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } config.SetCgrConfig(cfg) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) if err := dm.checkFilters("cgrates.org", []string{"FLTR_1"}); err == nil || err.Error() != "broken reference to filter: " { t.Error(err) } } func TestRemoveFilterIndexes(t *testing.T) { cfg := config.NewDefaultCGRConfig() defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) }() cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.CacheThresholdFilterIndexes: { Remote: true, }, } cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetIndexes: func(ctx *context.Context, args, reply any) error { return utils.ErrNotImplemented }, }, } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(db, cfg.CacheCfg(), connMgr) fp3 := &Filter{ Tenant: "cgrates.org", ID: "Filter3", Rules: []*FilterRule{ { Element: "~*req.Destination", Type: utils.MetaString, Values: []string{"30", "50"}, }, }} if err := dm.SetFilter(fp3, true); err != nil { t.Error(err) } if err := removeFilterIndexesForFilter(dm, utils.CacheThresholdFilterIndexes, "cgrates.org", []string{"Filter3"}, utils.StringSet{ "Filter3:THD1": {}, }); err != nil { t.Error(err) } config.SetCgrConfig(cfg) if err := removeFilterIndexesForFilter(dm, utils.CacheThresholdFilterIndexes, "cgrates.org", []string{"Filter3"}, utils.StringSet{ "Filter3:THD1": {}, }); err == nil || err != utils.ErrUnsupporteServiceMethod { t.Error(err) } } func TestGetDispatcherProfileErr(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpCache := Cache defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmpCache }() Cache.Clear(nil) cfg.DataDbCfg().Items = map[string]*config.ItemOpt{ utils.MetaDispatcherProfiles: { Remote: true, }, } cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator)} db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- &ccMock{ calls: map[string]func(ctx *context.Context, args any, reply any) error{ utils.ReplicatorSv1GetDispatcherProfile: func(ctx *context.Context, args, reply any) error { return utils.ErrDSPProfileNotFound }, }, } connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaReplicator): clientConn, }) dm := NewDataManager(db, cfg.CacheCfg(), connMgr) // dp := &DispatcherProfile{ // Tenant: "cgrates.org", // ID: "DSP_1", // Subsystems: []string{"*any"}, // FilterIDs: []string{"*string:~*req.Account:1001"}, // ActivationInterval: &utils.ActivationInterval{ // ActivationTime: time.Date(2014, 7, 29, 15, 00, 0, 0, time.UTC), // }, // } Cache.Set(utils.MetaDispatcherProfiles, "cgrates:Dsp1", nil, []string{}, true, utils.NonTransactional) if _, err := dm.GetDispatcherProfile("cgrates.org", "Dsp1", true, false, utils.NonTransactional); err == nil || err != utils.ErrDSPProfileNotFound { t.Error(err) } var dm2 *DataManager if _, err := dm2.GetDispatcherProfile("cgrates.org", "Dsp1", false, true, utils.NonTransactional); err == nil || err != utils.ErrNoDatabaseConn { t.Error(err) } config.SetCgrConfig(cfg) if _, err := dm.GetDispatcherProfile("cgrates.org", "Dsp1", false, true, utils.NonTransactional); err == nil || err != utils.ErrDSPProfileNotFound { t.Error(err) } } func TestRemoveIndexFiltersItem(t *testing.T) { cfg := config.NewDefaultCGRConfig() tmpCache := Cache defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) Cache = tmpCache }() Cache.Clear(nil) db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(db, cfg.CacheCfg(), nil) fltr := &Filter{ Tenant: "cgrates.org", ID: "FLTR_ACCOUNT_1001", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Account", Values: []string{"1001"}, }, }, } if err := dm.SetFilter(fltr, false); err != nil { t.Error(err) } thd := &ThresholdProfile{ Tenant: "cgrates.org", ID: "THD_ACNT_1001", FilterIDs: []string{"FLTR_ACCOUNT_1001"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 29, 15, 0, 0, 0, time.UTC), }, MaxHits: -1, MinHits: 0, MinSleep: 0, Blocker: false, Weight: 10.0, ActionIDs: []string{"TOPUP_MONETARY_10"}, Async: false, } if err := dm.SetThresholdProfile(thd, false); err != nil { t.Error(err) } indexes := map[string]utils.StringSet{ "*string:*req.Account:1001": { "THD_ACNT_1001": struct{}{}, }, } if err := dm.SetIndexes(utils.CacheReverseFilterIndexes, "cgrates.org:FLTR_ACCOUNT_1001:*threshold_filter_indexes", indexes, true, utils.NonTransactional); err != nil { t.Error(err) } if err := removeIndexFiltersItem(dm, utils.CacheThresholdFilterIndexes, "cgrates", "THD_ACNT_1001", []string{"FLTR_ACCOUNT_1001"}); err != nil { t.Error(err) } } func TestDmRemoveRouteProfileErr(t *testing.T) { cfg := config.NewDefaultCGRConfig() defer func() { config.SetCgrConfig(config.NewDefaultCGRConfig()) }() db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(db, cfg.CacheCfg(), nil) oldRp := &RouteProfile{ Tenant: "cgrates.org", ID: "RouteProfilePrefix4", Sorting: utils.MetaWeight, Routes: []*Route{ { ID: "route1", Weight: 10.0, RouteParameters: "param1", }, }, Weight: 0, } dm.dataDB = &DataDBMock{ GetRouteProfileDrvF: func(tenant, id string) (rp *RouteProfile, err error) { return oldRp, nil }, RemoveRouteProfileDrvF: func(tenant, id string) error { return nil }, } if err := dm.RemoveRouteProfile("cgrates.org", "RP1", true); err == nil || err != utils.ErrNotImplemented { t.Error(err) } dm.dataDB = &DataDBMock{ GetRouteProfileDrvF: func(tenant, id string) (rp *RouteProfile, err error) { return oldRp, nil }, } if err := dm.RemoveRouteProfile("cgrates.org", "RP1", true); err == nil || err != utils.ErrNotImplemented { t.Error(err) } dm.dataDB = &DataDBMock{} if err := dm.RemoveRouteProfile("cgrates.org", "RP1", true); err == nil || err != utils.ErrNotImplemented { t.Error(err) } } func TestDmCheckFiltersRmt(t *testing.T) { cfg := config.NewDefaultCGRConfig() defer func() { cfg2 := config.NewDefaultCGRConfig() config.SetCgrConfig(cfg2) }() Cache.Clear(nil) cfg.DataDbCfg().Items[utils.MetaFilters].Remote = true cfg.DataDbCfg().RmtConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1)} db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } clientConn := make(chan birpc.ClientConnector, 1) clientConn <- clMock(func(serviceMethod string, _, _ any) error { if serviceMethod == utils.ReplicatorSv1GetFilter { return nil } return utils.ErrNotFound }) dm := NewDataManager(db, cfg.CacheCfg(), NewConnManager(cfg, map[string]chan birpc.ClientConnector{ utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicatorSv1): clientConn, })) dm.SetFilter(&Filter{ Tenant: "cgrates.org", ID: "FLTR1", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.Route", Values: []string{"RouteProfile2"}, }, }, }, true) config.SetCgrConfig(cfg) if err := dm.checkFilters("cgrates.org", []string{"*string:~*req.Destination:1002", "*gte:~*req.Duration:20m", "FLTR1", "FLTR2"}); err == nil { t.Error(err) } //unfinished } func TestDmRebuildReverseForPrefix(t *testing.T) { testCases := []struct { desc string prefix string expectErr bool }{ { desc: "Valid prefix - ReverseDestinationPrefix", prefix: utils.ReverseDestinationPrefix, expectErr: false, }, { desc: "Valid prefix - AccountActionPlansPrefix", prefix: utils.AccountActionPlansPrefix, expectErr: false, }, { desc: "Invalid prefix", prefix: "invalid_prefix", expectErr: true, }, } cfg := config.NewDefaultCGRConfig() db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(db, cfg.CacheCfg(), nil) dm.SetDestination(&Destination{ Id: "Dest", Prefixes: []string{"1001", "1002"}, }, "") apls := []*ActionPlan{ { Id: "DisableBal", AccountIDs: utils.StringMap{"cgrates:1001": true}, }, { Id: "MoreMinutes", AccountIDs: utils.StringMap{"cgrates:1002": true}, }, } dm.SetAccount(&Account{ID: "cgrates:org:1001"}) dm.SetAccount(&Account{ID: "cgrates:org:1002"}) for _, apl := range apls { dm.SetActionPlan(apl.Id, apl, true, "") } for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { err := dm.RebuildReverseForPrefix(tc.prefix) if tc.expectErr { if err == nil { t.Fatal("Expected error, got nil") } } else { if err != nil { t.Fatalf("Expected no error, got: %v", err) } } }) } } func TestDmUpdateReverseDestination(t *testing.T) { cfg := config.NewDefaultCGRConfig() db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(db, cfg.CacheCfg(), nil) dst := &Destination{Id: "OldDest", Prefixes: []string{"+494", "+495", "+496"}} dst2 := &Destination{Id: "NewDest", Prefixes: []string{"+497", "+498", "+499"}} if _, rcvErr := dm.GetReverseDestination(dst.Id, false, true, utils.NonTransactional); rcvErr != utils.ErrNotFound { t.Error(rcvErr) } if err := dm.SetReverseDestination(dst.Id, dst.Prefixes, utils.NonTransactional); err != nil { t.Error(err) } for i := range dst.Prefixes { if rcv, err := dm.GetReverseDestination(dst.Prefixes[i], false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual([]string{dst.Id}, rcv) { t.Errorf("Expecting: %v, received: %v", []string{dst.Id}, rcv) } } if err := dm.UpdateReverseDestination(dst, dst2, utils.NonTransactional); err != nil { t.Error(err) } for i := range dst.Prefixes { if rcv, err := dm.GetReverseDestination(dst2.Prefixes[i], false, true, utils.NonTransactional); err != nil { t.Error(err) } else if !reflect.DeepEqual([]string{dst2.Id}, rcv) { t.Errorf("Expecting: %v, received: %v", []string{dst.Id}, rcv) } } } func TestIndxFilterContains(t *testing.T) { cfg := config.NewDefaultCGRConfig() idb, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items) if dErr != nil { t.Error(dErr) } dm := NewDataManager(idb, cfg.CacheCfg(), nil) ft := &Filter{ Tenant: "cgrates.org", ID: "Filter1", Rules: []*FilterRule{ { Type: utils.MetaContains, Element: "~*req.EventType", Values: []string{"Ev"}, }, }, } if err := dm.SetFilter(ft, true); err != nil { t.Error(err) } fs := &Filter{ Tenant: "cgrates.org", ID: "Filter2", Rules: []*FilterRule{ { Type: utils.MetaString, Element: "~*req.EventType", Values: []string{"Event1"}, }, }, } if err := dm.SetFilter(fs, true); err != nil { t.Error(err) } th := &ThresholdProfile{ Tenant: "cgrates.org", ID: "THD_Test", ActivationInterval: &utils.ActivationInterval{}, FilterIDs: []string{"Filter1", "Filter2"}, MaxHits: 12, MinSleep: 0, Blocker: true, Weight: 1.4, ActionIDs: []string{}, } if err := dm.SetThresholdProfile(th, true); err != nil { t.Error(err) } eIdxes := map[string]utils.StringSet{ "*string:*req.EventType:Event1": { "THD_Test": struct{}{}, }, } if rcvIdx, err := dm.GetIndexes( utils.CacheThresholdFilterIndexes, th.Tenant, false, false); err != nil { t.Error(err) } else if !reflect.DeepEqual(eIdxes, rcvIdx) { t.Errorf("Expecting %+v, received: %+v", eIdxes, rcvIdx) } }