diff --git a/engine/caches_test.go b/engine/caches_test.go new file mode 100644 index 000000000..4f84a24f0 --- /dev/null +++ b/engine/caches_test.go @@ -0,0 +1,241 @@ +/* +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 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package engine + +import ( + "testing" + "time" + + "github.com/cgrates/birpc" + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" + "github.com/cgrates/ltcache" +) + +func TestCacheSSetWithReplicateTrue(t *testing.T) { + Cache.Clear(nil) + args := &utils.ArgCacheReplicateSet{ + CacheID: "chID", + ItemID: "itemID", + Value: &utils.CachedRPCResponse{Result: "reply", Error: nil}, + GroupIDs: []string{"groupId", "groupId"}, + } + cfg := config.NewDefaultCGRConfig() + cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg)} + cfg.CacheCfg().Partitions = map[string]*config.CacheParamCfg{ + args.CacheID: { + Replicate: true, + }, + } + + db := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + dm := NewDataManager(db, cfg.CacheCfg(), nil) + clientconn := make(chan birpc.ClientConnector, 1) + clientconn <- &ccMock{ + calls: map[string]func(_ *context.Context, args interface{}, reply interface{}) error{ + utils.CacheSv1ReplicateSet: func(_ *context.Context, args, reply interface{}) error { + *reply.(*string) = "reply" + return nil + }, + }, + } + connMgr := NewConnManager(cfg) + connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg), utils.CacheSv1, clientconn) + tscache := ltcache.NewTransCache( + map[string]*ltcache.CacheConfig{ + ltcache.DefaultCacheInstance: { + MaxItems: 3, + TTL: time.Second * 1, + StaticTTL: true, + OnEvicted: func(itmID string, value interface{}) { + + }, + }, + }, + ) + casheS := &CacheS{ + cfg: cfg, + dm: dm, + tCache: tscache, + connMgr: connMgr, + } + if err := casheS.SetWithReplicate(context.Background(), args); err != nil { + t.Error(err) + } +} + +func TestCacheSSetWithReplicateFalse(t *testing.T) { + Cache.Clear(nil) + args := &utils.ArgCacheReplicateSet{ + CacheID: "chID", + ItemID: "itemID", + Value: &utils.CachedRPCResponse{Result: "reply", Error: nil}, + GroupIDs: []string{"groupId", "groupId"}, + } + cfg := config.NewDefaultCGRConfig() + cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg)} + cfg.CacheCfg().Partitions = map[string]*config.CacheParamCfg{ + args.CacheID: { + Replicate: false, + }, + } + + db := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + dm := NewDataManager(db, cfg.CacheCfg(), nil) + clientconn := make(chan birpc.ClientConnector, 1) + clientconn <- &ccMock{ + calls: map[string]func(_ *context.Context, args interface{}, reply interface{}) error{ + utils.CacheSv1ReplicateSet: func(_ *context.Context, args, reply interface{}) error { + *reply.(*string) = "reply" + return nil + }, + }, + } + connMgr := NewConnManager(cfg) + connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg), utils.CacheSv1, clientconn) + tscache := ltcache.NewTransCache( + map[string]*ltcache.CacheConfig{ + ltcache.DefaultCacheInstance: { + MaxItems: 3, + TTL: time.Second * 1, + StaticTTL: true, + OnEvicted: func(itmID string, value interface{}) { + + }, + }, + }, + ) + casheS := &CacheS{ + cfg: cfg, + dm: dm, + tCache: tscache, + connMgr: connMgr, + } + if err := casheS.SetWithReplicate(context.Background(), args); err != nil { + t.Error(err) + } +} + +func TestCacheSGetWithRemote(t *testing.T) { + Cache.Clear(nil) + args := &utils.ArgsGetCacheItemWithAPIOpts{ + + ArgsGetCacheItem: utils.ArgsGetCacheItem{ + CacheID: "cacheID", + ItemID: "itemId", + }, + } + cfg := config.NewDefaultCGRConfig() + db := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + dm := NewDataManager(db, cfg.CacheCfg(), nil) + cfg.CacheCfg().RemoteConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.RemoteConnsCfg)} + cfg.CacheCfg().Partitions = map[string]*config.CacheParamCfg{ + args.CacheID: { + Remote: true, + }, + } + clientconn := make(chan birpc.ClientConnector, 1) + clientconn <- &ccMock{ + calls: map[string]func(_ *context.Context, args interface{}, reply interface{}) error{ + utils.CacheSv1GetItem: func(_ *context.Context, args, reply interface{}) error { + + return nil + }, + }, + } + connMgr := NewConnManager(cfg) + connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.RemoteConnsCfg), utils.CacheSv1GetItem, clientconn) + + tscache := ltcache.NewTransCache( + map[string]*ltcache.CacheConfig{ + "cacheID": { + MaxItems: 3, + TTL: time.Second * 1, + StaticTTL: true, + OnEvicted: func(itmID string, value interface{}) { + + }, + }, + }) + chS := &CacheS{ + cfg: cfg, + dm: dm, + tCache: tscache, + connMgr: connMgr, + } + var reply interface{} = "str" + if err := chS.V1GetItemWithRemote(context.Background(), args, &reply); err != nil { + t.Error(err) + } +} + +func TestCacheSGetWithRemoteFalse(t *testing.T) { + Cache.Clear(nil) + args := &utils.ArgsGetCacheItemWithAPIOpts{ + + ArgsGetCacheItem: utils.ArgsGetCacheItem{ + CacheID: "cacheID", + ItemID: "itemId", + }, + } + cfg := config.NewDefaultCGRConfig() + db := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + dm := NewDataManager(db, cfg.CacheCfg(), nil) + cfg.CacheCfg().RemoteConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.RemoteConnsCfg)} + cfg.CacheCfg().Partitions = map[string]*config.CacheParamCfg{ + args.CacheID: { + Remote: false, + }, + } + clientconn := make(chan birpc.ClientConnector, 1) + clientconn <- &ccMock{ + calls: map[string]func(_ *context.Context, args interface{}, reply interface{}) error{ + utils.CacheSv1GetItem: func(_ *context.Context, args, reply interface{}) error { + + return nil + }, + }, + } + connMgr := NewConnManager(cfg) + connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.RemoteConnsCfg), utils.CacheSv1GetItem, clientconn) + + tscache := ltcache.NewTransCache( + map[string]*ltcache.CacheConfig{ + "cacheID": { + MaxItems: 3, + TTL: time.Second * 1, + StaticTTL: true, + OnEvicted: func(itmID string, value interface{}) { + + }, + }, + }) + chS := &CacheS{ + cfg: cfg, + dm: dm, + tCache: tscache, + connMgr: connMgr, + } + + var reply interface{} = "str" + if err := chS.V1GetItemWithRemote(context.Background(), args, &reply); err == nil || err != utils.ErrNotFound { + t.Errorf("Expected error <%v>, received error <%v>", utils.ErrNotFound, err) + } +} diff --git a/engine/cdrs_test.go b/engine/cdrs_test.go index b119c7947..1b863c5ac 100644 --- a/engine/cdrs_test.go +++ b/engine/cdrs_test.go @@ -2622,3 +2622,216 @@ func TestCDRsV1ProcessEventWithGetCacheGet(t *testing.T) { t.Errorf("\nExpected <%+v> \n,received <%+v>", expected, cgrEv) } } + +func TestCDRServerAccountSRefundCharges(t *testing.T) { + testCache := Cache + tmpC := config.CgrConfig() + tmpCM := connMgr + defer func() { + Cache = testCache + config.SetCgrConfig(tmpC) + connMgr = tmpCM + }() + + cfg := config.NewDefaultCGRConfig() + cfg.CdrsCfg().AccountSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, + utils.AccountSConnsCfg)} + + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + connMng := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + fltrs := NewFilterS(cfg, nil, dm) + Cache = NewCacheS(cfg, dm, nil, nil) + newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng) + ccM := &ccMock{ + calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{ + utils.AccountSv1RefundCharges: func(ctx *context.Context, args, reply interface{}) error { + *reply.(*string) = "" + return nil + }, + }, + } + rpcInternal := make(chan birpc.ClientConnector, 1) + rpcInternal <- ccM + newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, + utils.AccountSConnsCfg), utils.AccountSv1, rpcInternal) + + apiOpts := map[string]interface{}{ + utils.MetaAccountSCost: &utils.EventCharges{}, + utils.MetaSubsys: utils.AccountSConnsCfg, + } + eChrgs := &utils.EventCharges{ + Abstracts: utils.NewDecimal(500, 0), + Concretes: utils.NewDecimal(400, 0), + Charges: []*utils.ChargeEntry{ + { + ChargingID: "GENUUID", //will be changed + CompressFactor: 1, + }, + { + ChargingID: "GENUUID2", //will be changed + CompressFactor: 1, + }, + }, + Accounting: map[string]*utils.AccountCharge{ + "GENUUID2": { + BalanceID: "CB2", + Units: utils.NewDecimal(2, 0), + BalanceLimit: utils.NewDecimal(-1, 0), + }, + "GENUUID": { + BalanceID: "CB1", + Units: utils.NewDecimal(7, 0), + BalanceLimit: utils.NewDecimal(-200, 0), + UnitFactorID: "GENNUUID_FACTOR", + }, + }, + UnitFactors: map[string]*utils.UnitFactor{ + "GENNUUID_FACTOR": { + Factor: utils.NewDecimal(100, 0), + }, + }, + Rating: make(map[string]*utils.RateSInterval), + Rates: make(map[string]*utils.IntervalRate), + Accounts: make(map[string]*utils.Account), + } + err := newCDRSrv.accountSRefundCharges(context.Background(), "cgrates.org", eChrgs, apiOpts) + if err != nil { + t.Errorf("\nExpected <%+v> \n, received <%+v>", nil, err) + } + + expected := &utils.EventCharges{ + Abstracts: utils.NewDecimal(500, 0), + Concretes: utils.NewDecimal(400, 0), + Charges: []*utils.ChargeEntry{ + { + ChargingID: "GENUUID", //will be changed + CompressFactor: 1, + }, + { + ChargingID: "GENUUID2", //will be changed + CompressFactor: 1, + }, + }, + Accounting: map[string]*utils.AccountCharge{ + "GENUUID2": { + BalanceID: "CB2", + Units: utils.NewDecimal(2, 0), + BalanceLimit: utils.NewDecimal(-1, 0), + }, + "GENUUID": { + BalanceID: "CB1", + Units: utils.NewDecimal(7, 0), + BalanceLimit: utils.NewDecimal(-200, 0), + UnitFactorID: "GENNUUID_FACTOR", + }, + }, + UnitFactors: map[string]*utils.UnitFactor{ + "GENNUUID_FACTOR": { + Factor: utils.NewDecimal(100, 0), + }, + }, + Rating: make(map[string]*utils.RateSInterval), + Rates: make(map[string]*utils.IntervalRate), + Accounts: make(map[string]*utils.Account), + } + if !reflect.DeepEqual(expected, eChrgs) { + t.Errorf("\nExpected <%+v> \n,received <%+v>", expected, eChrgs) + } +} +func TestCDRServerAccountSRefundChargesErr(t *testing.T) { + testCache := Cache + tmpC := config.CgrConfig() + tmpCM := connMgr + defer func() { + Cache = testCache + config.SetCgrConfig(tmpC) + connMgr = tmpCM + }() + + cfg := config.NewDefaultCGRConfig() + cfg.CdrsCfg().AccountSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, + utils.AccountSConnsCfg)} + + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + connMng := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + fltrs := NewFilterS(cfg, nil, dm) + Cache = NewCacheS(cfg, dm, nil, nil) + newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng) + ccM := &ccMock{ + calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{ + utils.ChargerSv1ProcessEvent: func(ctx *context.Context, args, reply interface{}) error { + *reply.(*string) = "" + return nil + }, + }, + } + rpcInternal := make(chan birpc.ClientConnector, 1) + rpcInternal <- ccM + newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, + utils.AccountSConnsCfg), utils.AccountSv1, rpcInternal) + + apiOpts := map[string]interface{}{ + utils.MetaAccountSCost: &utils.EventCharges{}, + utils.MetaSubsys: utils.AccountSConnsCfg, + } + eChrgs := &utils.EventCharges{ + Abstracts: utils.NewDecimal(500, 0), + Concretes: utils.NewDecimal(400, 0), + } + expErr := "UNSUPPORTED_SERVICE_METHOD" + err := newCDRSrv.accountSRefundCharges(context.Background(), "cgrates.org", eChrgs, apiOpts) + if err == nil || err.Error() != expErr { + t.Errorf("\nExpected error <%v> \n, received error <%v>", expErr, err) + } + +} + +func TestPopulateCost(t *testing.T) { + + ev := &utils.CGREvent{ + Tenant: "cgrates.org", + Event: map[string]interface{}{ + utils.Usage: "10s", + }, + APIOpts: map[string]interface{}{ + utils.MetaAccountSCost: &utils.EventCharges{ + Concretes: utils.NewDecimal(400, 0), + }, + }, + } + exp := utils.NewDecimal(400, 0) + if rcv := populateCost(ev.APIOpts); !reflect.DeepEqual(exp, rcv) { + t.Errorf("Expected <%+v>, Received <%+v>", exp, rcv) + } + ev = &utils.CGREvent{ + Tenant: "cgrates.org", + Event: map[string]interface{}{ + utils.Usage: "10s", + }, + APIOpts: map[string]interface{}{ + + utils.MetaRateSCost: utils.RateProfileCost{ + + Cost: utils.NewDecimal(400, 0), + }, + }, + } + if rcv := populateCost(ev.APIOpts); !reflect.DeepEqual(exp, rcv) { + t.Errorf("Expected <%+v>, Received <%+v>", exp, rcv) + } + ev = &utils.CGREvent{ + Tenant: "cgrates.org", + Event: map[string]interface{}{ + utils.Usage: "10s", + }, + APIOpts: map[string]interface{}{ + + utils.MetaCost: 102.1, + }, + } + if rcv := populateCost(ev.APIOpts); rcv != nil { + t.Errorf("Expected <%+v>, Received <%+v>", nil, rcv) + } +}