mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 10:06:24 +05:00
1139 lines
30 KiB
Go
1139 lines
30 KiB
Go
/*
|
|
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 <https://www.gnu.org/licenses/>
|
|
*/
|
|
package engine
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"regexp"
|
|
"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 TestCachesReplicateRemove(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg)}
|
|
cfg.CacheCfg().Partitions = map[string]*config.CacheParamCfg{
|
|
utils.ReplicatorSv1GetDispatcherHost: {
|
|
Replicate: true,
|
|
},
|
|
}
|
|
db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items)
|
|
if dErr != nil {
|
|
t.Error(dErr)
|
|
}
|
|
dm := NewDataManager(db, cfg.CacheCfg(), nil)
|
|
clientconn := make(chan birpc.ClientConnector, 1)
|
|
clientconn <- &ccMock{
|
|
calls: map[string]func(ctx *context.Context, args any, reply any) error{
|
|
utils.CacheSv1ReplicateRemove: func(ctx *context.Context, args, reply any) error {
|
|
*reply.(*string) = utils.OK
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{
|
|
utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg): clientconn,
|
|
})
|
|
chS := CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
}
|
|
SetConnManager(connMgr)
|
|
if err := chS.ReplicateRemove(utils.ReplicatorSv1GetDispatcherHost, "itm_id"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCacheSSetWithReplicate(t *testing.T) {
|
|
Cache.Clear(nil)
|
|
args := &utils.ArgCacheReplicateSet{
|
|
CacheID: utils.ReplicatorSv1GetActions,
|
|
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, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items)
|
|
if dErr != nil {
|
|
t.Error(dErr)
|
|
}
|
|
dm := NewDataManager(db, cfg.CacheCfg(), 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 {
|
|
|
|
*reply.(*string) = "reply"
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{
|
|
utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg): clientconn,
|
|
})
|
|
ltcache := ltcache.NewTransCache(map[string]*ltcache.CacheConfig{
|
|
args.CacheID: {
|
|
MaxItems: 2,
|
|
},
|
|
})
|
|
cacheS := &CacheS{
|
|
dm: dm,
|
|
cfg: cfg,
|
|
tCache: ltcache,
|
|
}
|
|
SetConnManager(connMgr)
|
|
if err := cacheS.SetWithReplicate(args); err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
}
|
|
|
|
func TestCacheSV1GetItemIDs(t *testing.T) {
|
|
args := &utils.ArgsGetCacheItemIDsWithAPIOpts{
|
|
APIOpts: map[string]any{},
|
|
Tenant: "cgrates.org",
|
|
ArgsGetCacheItemIDs: utils.ArgsGetCacheItemIDs{
|
|
CacheID: "cacheID",
|
|
ItemIDPrefix: "itemID",
|
|
},
|
|
}
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheID": {
|
|
MaxItems: 3,
|
|
TTL: time.Second * 1,
|
|
StaticTTL: true,
|
|
OnEvicted: []func(itmID string, value interface{}){
|
|
func(itmID string, value any) {
|
|
|
|
},
|
|
},
|
|
},
|
|
})
|
|
tscache.Set("cacheID", "itemID", "", []string{}, true, "tId")
|
|
|
|
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)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
reply := &[]string{}
|
|
exp := &[]string{"itemID"}
|
|
if err := chS.V1GetItemIDs(context.Background(), args, reply); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(reply, exp) {
|
|
t.Errorf("expected %+v,received %+v", utils.ToJSON(exp), utils.ToJSON(reply))
|
|
}
|
|
tscache.Remove("cacheID", "itemID", true, utils.NonTransactional)
|
|
if err := chS.V1GetItemIDs(context.Background(), args, reply); err == nil || err != utils.ErrNotFound {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1HasItem(t *testing.T) {
|
|
args := &utils.ArgsGetCacheItemWithAPIOpts{
|
|
APIOpts: map[string]any{},
|
|
Tenant: "cgrates.org",
|
|
ArgsGetCacheItem: utils.ArgsGetCacheItem{
|
|
CacheID: "cacheID",
|
|
ItemID: "itemID",
|
|
},
|
|
}
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheID": {
|
|
MaxItems: 3,
|
|
TTL: time.Second * 1,
|
|
StaticTTL: true,
|
|
OnEvicted: []func(itmID string, value interface{}){
|
|
func(itmID string, value any) {
|
|
|
|
},
|
|
},
|
|
},
|
|
})
|
|
tscache.Set("cacheID", "itemID", "", []string{}, true, "tId")
|
|
|
|
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)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
reply := utils.BoolPointer(false)
|
|
if err := chS.V1HasItem(context.Background(), args, reply); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1GetItemWithRemote(t *testing.T) {
|
|
args := &utils.ArgsGetCacheItemWithAPIOpts{
|
|
|
|
ArgsGetCacheItem: utils.ArgsGetCacheItem{
|
|
CacheID: "cacheID",
|
|
ItemID: "itemId",
|
|
},
|
|
}
|
|
cfg := config.NewDefaultCGRConfig()
|
|
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(ctx *context.Context, args any, reply any) error{
|
|
utils.CacheSv1GetItem: func(ctx *context.Context, args, reply any) error {
|
|
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{
|
|
utils.ConcatenatedKey(utils.MetaInternal, utils.RemoteConnsCfg): clientconn,
|
|
},
|
|
)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheID": {
|
|
MaxItems: 3,
|
|
TTL: time.Second * 1,
|
|
StaticTTL: true,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {
|
|
|
|
},
|
|
},
|
|
},
|
|
})
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
SetConnManager(connMgr)
|
|
var reply any = "str"
|
|
if err := chS.V1GetItemWithRemote(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1GetItem(t *testing.T) {
|
|
args := &utils.ArgsGetCacheItemWithAPIOpts{
|
|
ArgsGetCacheItem: utils.ArgsGetCacheItem{
|
|
CacheID: "cacheID",
|
|
ItemID: "itemID",
|
|
},
|
|
}
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheID": {
|
|
MaxItems: 3,
|
|
TTL: time.Second * 1,
|
|
StaticTTL: true,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
})
|
|
tscache.Set("cacheID", "itemID", "value", []string{}, true, "tId")
|
|
|
|
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)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
var reply any
|
|
if err := chS.V1GetItem(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if val, cancast := reply.(string); cancast {
|
|
if val != "value" {
|
|
t.Errorf("expected value,received %v", val)
|
|
}
|
|
}
|
|
tscache.Remove("cacheID", "itemID", true, utils.NonTransactional)
|
|
if err := chS.V1GetItem(context.Background(), args, &reply); err == nil || err != utils.ErrNotFound {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1GetItemExpiryTime(t *testing.T) {
|
|
cacheID := "testCache"
|
|
itemID := "testItem"
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
cacheID: {
|
|
MaxItems: -1,
|
|
TTL: 30 * time.Minute,
|
|
},
|
|
})
|
|
chS := &CacheS{
|
|
tCache: tscache,
|
|
}
|
|
chS.tCache.Set(cacheID, itemID, "value", []string{}, true, "")
|
|
want := time.Now().Add(30 * time.Minute)
|
|
|
|
var got time.Time
|
|
if err := chS.V1GetItemExpiryTime(context.Background(),
|
|
&utils.ArgsGetCacheItemWithAPIOpts{
|
|
ArgsGetCacheItem: utils.ArgsGetCacheItem{
|
|
CacheID: cacheID,
|
|
ItemID: itemID,
|
|
},
|
|
}, &got); err != nil {
|
|
t.Fatalf("V1GetItemExpiryTime(%q,%q): got unexpected err=%v", cacheID, itemID, err)
|
|
}
|
|
if diff := want.Sub(got); diff < 0 || diff > time.Millisecond {
|
|
t.Errorf("V1GetItemExpiryTime(%q,%q) = %v, want %v (diff %v, margin 1ms)",
|
|
cacheID, itemID, got.Format(time.StampMicro), want.Format(time.StampMicro), diff)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1RemoveItem(t *testing.T) {
|
|
args := &utils.ArgsGetCacheItemWithAPIOpts{
|
|
ArgsGetCacheItem: utils.ArgsGetCacheItem{
|
|
CacheID: "cacheID",
|
|
ItemID: "itemID",
|
|
},
|
|
}
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheID": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
})
|
|
tscache.Set("cacheID", "itemID", "value", []string{}, true, "tId")
|
|
|
|
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)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
var reply string
|
|
if err := chS.V1RemoveItem(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("expected %v,received %v", utils.OK, reply)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1RemoveItems(t *testing.T) {
|
|
args := utils.NewAttrReloadCacheWithOpts()
|
|
args.DestinationIDs = []string{"dest1", "dest2", "dest3"}
|
|
args.ResourceIDs = []string{"res1", "res2", "res3"}
|
|
args.FilterIDs = []string{"fltr1", "filtr2", "filtr3"}
|
|
cfgCache := map[string]*ltcache.CacheConfig{
|
|
utils.CacheDestinations: {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
utils.CacheResources: {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
utils.CacheFilters: {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
}
|
|
args2 := map[string][]string{
|
|
utils.CacheDestinations: {"dest1", "dest2", "dest3"},
|
|
utils.CacheResources: {"res1", "res2", "res3"},
|
|
utils.CacheFilters: {"fltr1", "filtr2", "filtr3"},
|
|
}
|
|
tscache := ltcache.NewTransCache(cfgCache)
|
|
|
|
for keyId := range cfgCache {
|
|
if itemids, has := args2[keyId]; has {
|
|
for _, itemid := range itemids {
|
|
tscache.Set(keyId, itemid, "value", []string{}, true, "tId")
|
|
}
|
|
}
|
|
}
|
|
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)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
|
|
reply := "error"
|
|
|
|
if err := chS.V1RemoveItems(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("expected %v,received %v", utils.OK, reply)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1Clear(t *testing.T) {
|
|
args := &utils.AttrCacheIDsWithAPIOpts{
|
|
APIOpts: map[string]any{},
|
|
Tenant: "cgrates.org",
|
|
CacheIDs: []string{"cacheID", "cacheID2", "cacheID3"},
|
|
}
|
|
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)
|
|
|
|
cfgCache := map[string]*ltcache.CacheConfig{
|
|
"cacheID": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
"cacheID2": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
"cacheID3": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
}
|
|
tscache := ltcache.NewTransCache(cfgCache)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
reply := "error"
|
|
if err := chS.V1Clear(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1ReplicateSet(t *testing.T) {
|
|
fltr := &Filter{
|
|
Tenant: "cgrates",
|
|
ID: "filterID",
|
|
}
|
|
args := &utils.ArgCacheReplicateSet{
|
|
CacheID: "cacheID",
|
|
ItemID: "itemID",
|
|
Value: fltr,
|
|
}
|
|
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)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheID": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
}},
|
|
)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
reply := "reply"
|
|
if err := chS.V1ReplicateSet(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("expected %+v,received %+v", utils.OK, reply)
|
|
}
|
|
val, has := chS.tCache.Get(args.CacheID, args.ItemID)
|
|
|
|
if !has {
|
|
t.Error("has no value")
|
|
}
|
|
|
|
if !reflect.DeepEqual(val, fltr) {
|
|
t.Errorf("expected %+v,received %+v", "", utils.ToJSON(val))
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1GetCacheStats(t *testing.T) {
|
|
args := &utils.AttrCacheIDsWithAPIOpts{
|
|
APIOpts: map[string]any{},
|
|
Tenant: "cgrates.org",
|
|
CacheIDs: []string{"cacheID", "cacheID2", "cacheID3"},
|
|
}
|
|
reply := map[string]*ltcache.CacheStats{}
|
|
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)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheID": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
"cacheID2": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
"cacheID3": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
for i, id := range args.CacheIDs {
|
|
|
|
tscache.Set(id, fmt.Sprintf("%s%d", "item", i), "value", []string{}, true, "tId")
|
|
}
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
exp := map[string]*ltcache.CacheStats{
|
|
"cacheID": {Items: 1, Groups: 0},
|
|
"cacheID2": {Items: 1, Groups: 0},
|
|
"cacheID3": {Items: 1, Groups: 0},
|
|
}
|
|
if err := chS.V1GetCacheStats(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(reply, exp) {
|
|
t.Errorf("expected %v,received %v", utils.ToJSON(reply), utils.ToJSON(exp))
|
|
}
|
|
|
|
}
|
|
|
|
func TestCachesPrecache(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
cfg.CacheCfg().Partitions = map[string]*config.CacheParamCfg{
|
|
utils.CacheDestinations: {
|
|
Limit: 1,
|
|
Precache: true,
|
|
TTL: time.Minute * 2,
|
|
Remote: true,
|
|
},
|
|
}
|
|
pcI := map[string]chan struct{}{
|
|
utils.CacheDestinations: make(chan struct{})}
|
|
db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items)
|
|
if dErr != nil {
|
|
t.Error(dErr)
|
|
}
|
|
dm := NewDataManager(db, cfg.CacheCfg(), nil)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
pcItems: pcI,
|
|
}
|
|
if err := chS.Precache(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
}
|
|
|
|
func TestV1PrecacheStatus(t *testing.T) {
|
|
args := &utils.AttrCacheIDsWithAPIOpts{
|
|
APIOpts: map[string]any{},
|
|
Tenant: "cgrates.org",
|
|
CacheIDs: []string{utils.CacheFilters},
|
|
}
|
|
cfg := config.NewDefaultCGRConfig()
|
|
|
|
pcI := map[string]chan struct{}{
|
|
utils.CacheFilters: make(chan struct{}),
|
|
}
|
|
db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items)
|
|
if dErr != nil {
|
|
t.Error(dErr)
|
|
}
|
|
dm := NewDataManager(db, cfg.CacheCfg(), nil)
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
pcItems: pcI,
|
|
}
|
|
|
|
reply := map[string]string{}
|
|
exp := map[string]string{
|
|
utils.CacheFilters: utils.MetaPrecaching,
|
|
}
|
|
if err := chS.V1PrecacheStatus(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(exp, reply) {
|
|
t.Errorf("expected %+v,received %+v", exp, reply)
|
|
}
|
|
args.CacheIDs = []string{}
|
|
if err := chS.V1PrecacheStatus(context.Background(), args, &reply); err == nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCacheSV1HasGroup(t *testing.T) {
|
|
args := &utils.ArgsGetGroupWithAPIOpts{
|
|
ArgsGetGroup: utils.ArgsGetGroup{
|
|
CacheID: "cacheId",
|
|
GroupID: "groupId",
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
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)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheId": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
}},
|
|
)
|
|
tscache.Set("cacheId", "itemId", "value", []string{"groupId"}, true, "tId")
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
|
|
var reply bool
|
|
if err := chS.V1HasGroup(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if !reply {
|
|
t.Error("expected true,received false")
|
|
}
|
|
|
|
}
|
|
|
|
func TestCacheSV1HasGroupItemIDs(t *testing.T) {
|
|
args := &utils.ArgsGetGroupWithAPIOpts{
|
|
ArgsGetGroup: utils.ArgsGetGroup{
|
|
CacheID: "cacheId",
|
|
GroupID: "groupId",
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
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)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheId": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
}},
|
|
)
|
|
tscache.Set("cacheId", "itemId", "value", []string{"groupId"}, true, "tId")
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
var reply []string
|
|
exp := []string{"itemId"}
|
|
if err := chS.V1GetGroupItemIDs(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(exp, reply) {
|
|
t.Errorf("expected %+v,received %+v", exp, reply)
|
|
}
|
|
|
|
}
|
|
|
|
func TestV1RemoveGroup(t *testing.T) {
|
|
args := &utils.ArgsGetGroupWithAPIOpts{
|
|
ArgsGetGroup: utils.ArgsGetGroup{
|
|
CacheID: "cacheId",
|
|
GroupID: "groupId",
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
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)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheId": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
}},
|
|
)
|
|
tscache.Set("cacheId", "itemId", "value", []string{"groupId"}, true, "tId")
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
var reply string
|
|
|
|
if err := chS.V1RemoveGroup(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("expected %v,received %v", utils.OK, reply)
|
|
}
|
|
|
|
if has := tscache.HasGroup(args.CacheID, args.GroupID); has {
|
|
t.Errorf("expected false,received %+v", has)
|
|
}
|
|
|
|
}
|
|
|
|
func TestCacheSV1ReplicateRemove(t *testing.T) {
|
|
args := &utils.ArgCacheReplicateRemove{
|
|
CacheID: "cacheID",
|
|
ItemID: "itemID",
|
|
APIOpts: map[string]any{},
|
|
Tenant: "cgrates.org",
|
|
}
|
|
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)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheId": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {},
|
|
},
|
|
}},
|
|
)
|
|
tscache.Set(args.CacheID, args.ItemID, "value", []string{"groupId"}, true, "tId")
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
var reply string
|
|
|
|
if err := chS.V1ReplicateRemove(context.Background(), args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("expected %v,received %v", utils.OK, reply)
|
|
}
|
|
|
|
if _, has := tscache.Get(args.CacheID, args.ItemID); has {
|
|
t.Errorf("expected false,received %+v", has)
|
|
}
|
|
}
|
|
|
|
func TestNewCacheS(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
cfg.CacheCfg().ReplicationConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg)}
|
|
cfg.CacheCfg().Partitions = map[string]*config.CacheParamCfg{
|
|
"cacheID": {
|
|
Limit: 3,
|
|
TTL: 2 * time.Minute,
|
|
StaticTTL: true,
|
|
Replicate: true,
|
|
},
|
|
}
|
|
db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items)
|
|
if dErr != nil {
|
|
t.Error(dErr)
|
|
}
|
|
dm := NewDataManager(db, cfg.CacheCfg(), nil)
|
|
clientconn := make(chan birpc.ClientConnector, 1)
|
|
clientconn <- &ccMock{
|
|
calls: map[string]func(ctx *context.Context, args any, reply any) error{
|
|
utils.CacheSv1ReplicateRemove: func(ctx *context.Context, args, reply any) error {
|
|
|
|
*reply.(*string) = "reply"
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{
|
|
utils.ConcatenatedKey(utils.MetaInternal, utils.ReplicationConnsCfg): clientconn,
|
|
})
|
|
expCacheS := &CacheS{}
|
|
SetConnManager(connMgr)
|
|
if c := NewCacheS(cfg, dm, &CapsStats{}); reflect.DeepEqual(expCacheS, c) {
|
|
t.Errorf("expected %+v,received %+v", utils.ToJSON(expCacheS), utils.ToJSON(c))
|
|
}
|
|
|
|
}
|
|
|
|
func TestCacheRemoveWithoutReplicate(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)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheId": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {
|
|
},
|
|
},
|
|
}},
|
|
)
|
|
tscache.Set("cacheID", "itemId", "value", []string{"groupId"}, true, "tId")
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
chS.RemoveWithoutReplicate("cacheID", "itemId", true, "tId")
|
|
|
|
if _, has := tscache.Get("cacheID", "itemId"); has {
|
|
t.Error("shouldn't exist")
|
|
}
|
|
}
|
|
func TestCacheRemoveGroup(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)
|
|
tscache := ltcache.NewTransCache(
|
|
map[string]*ltcache.CacheConfig{
|
|
"cacheId": {
|
|
MaxItems: 3,
|
|
TTL: time.Minute * 30,
|
|
StaticTTL: false,
|
|
OnEvicted: []func(itmID string, value any){
|
|
func(itmID string, value any) {
|
|
},
|
|
},
|
|
}},
|
|
)
|
|
tscache.Set("cacheID", "itemId", "value", []string{"groupId"}, true, "tId")
|
|
chS := &CacheS{
|
|
cfg: cfg,
|
|
dm: dm,
|
|
tCache: tscache,
|
|
}
|
|
chS.RemoveGroup("cacheID", "groupId")
|
|
if _, has := tscache.Get("cacheID", "itemId"); has {
|
|
t.Error("shouldn't exist")
|
|
}
|
|
|
|
}
|
|
|
|
func TestUpdateReplicationFilters(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
tmp := *Cache
|
|
defer func() {
|
|
*Cache = tmp
|
|
}()
|
|
Cache.Clear(nil)
|
|
Cache = NewCacheS(cfg, nil, nil)
|
|
Cache.tCache = ltcache.NewTransCache(map[string]*ltcache.CacheConfig{
|
|
utils.CacheReplicationHosts: {
|
|
MaxItems: 3,
|
|
},
|
|
})
|
|
objType, objID, connID := "obj", "id", "conn"
|
|
UpdateReplicationFilters("obj", "id", "conn")
|
|
if val, has := Cache.Get(utils.CacheReplicationHosts, objType+objID+utils.ConcatenatedKeySep+connID); !has {
|
|
t.Error("has no value")
|
|
} else if val.(string) != connID {
|
|
t.Errorf("expected %v,received %v", connID, val)
|
|
}
|
|
}
|
|
|
|
func TestReplicateMultipleIDs(t *testing.T) {
|
|
tmp := Cache
|
|
defer func() {
|
|
Cache = tmp
|
|
}()
|
|
Cache.Clear(nil)
|
|
cfg := config.NewDefaultCGRConfig()
|
|
cfg.ApierCfg().CachesConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches)}
|
|
cfg.AttributeSCfg().Enabled = true
|
|
cfg.CacheCfg().Partitions = map[string]*config.CacheParamCfg{
|
|
utils.CacheReplicationHosts: {
|
|
Limit: 3,
|
|
},
|
|
}
|
|
|
|
Cache = NewCacheS(cfg, nil, nil)
|
|
connClient := make(chan birpc.ClientConnector, 1)
|
|
connClient <- &ccMock{
|
|
calls: map[string]func(ctx *context.Context, args any, reply any) error{
|
|
utils.CacheSv1ReloadCache: func(ctx *context.Context, args, reply any) error {
|
|
*reply.(*string) = "reply"
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{
|
|
utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): connClient,
|
|
})
|
|
objType := "obj"
|
|
objIds := []string{"rpl1", "rpl2"}
|
|
method := utils.CacheSv1ReloadCache
|
|
args := &utils.AttrReloadCacheWithAPIOpts{
|
|
AccountActionPlanIDs: []string{"accID"},
|
|
}
|
|
if err := replicateMultipleIDs(connMgr, cfg.ApierCfg().CachesConns, false, objType, objIds, method, args); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := replicateMultipleIDs(connMgr, cfg.ApierCfg().CachesConns, true, objType, objIds, method, args); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
func TestCachesGetWithRemote(t *testing.T) {
|
|
Cache.Clear(nil)
|
|
args := &utils.ArgsGetCacheItemWithAPIOpts{
|
|
ArgsGetCacheItem: utils.ArgsGetCacheItem{
|
|
CacheID: utils.CacheTBLTPActionPlans,
|
|
ItemID: "cacheItem",
|
|
},
|
|
}
|
|
cfg := config.NewDefaultCGRConfig()
|
|
cfg.DataDbCfg().Items = map[string]*config.ItemOpt{
|
|
utils.CacheTBLTPActionPlans: {
|
|
Limit: 3,
|
|
Remote: false,
|
|
},
|
|
}
|
|
db, dErr := NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items)
|
|
if dErr != nil {
|
|
t.Error(dErr)
|
|
}
|
|
dm := NewDataManager(db, cfg.CacheCfg(), nil)
|
|
chS := 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.CacheSv1GetItem: func(ctx *context.Context, args, reply any) error {
|
|
*reply.(*string) = utils.OK
|
|
return utils.ErrNotFound
|
|
},
|
|
},
|
|
}
|
|
|
|
connMgr := NewConnManager(cfg, map[string]chan birpc.ClientConnector{
|
|
utils.ConcatenatedKey(utils.MetaInternal, utils.RemoteConnsCfg): clientconn,
|
|
})
|
|
SetConnManager(connMgr)
|
|
tpAc := &utils.TPActionTrigger{
|
|
BalanceId: "id",
|
|
Id: "STANDARD_TRIGGERS",
|
|
ThresholdType: "*min_balance",
|
|
ThresholdValue: 2,
|
|
Recurrent: false,
|
|
MinSleep: "0",
|
|
ExpirationDate: "date",
|
|
BalanceType: "*monetary",
|
|
BalanceDestinationIds: "FS_USERS",
|
|
ActionsId: "LOG_WARNING",
|
|
Weight: 10,
|
|
}
|
|
chS.tCache.Set(args.CacheID, "cacheItem", tpAc, []string{"cacheItem"}, true, utils.NonTransactional)
|
|
if val, err := chS.GetWithRemote(args); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(val, tpAc) {
|
|
t.Errorf("expected %v,received %v", utils.ToJSON(tpAc), utils.ToJSON(val))
|
|
}
|
|
chS.tCache.Remove(utils.CacheTBLTPActionPlans, "cacheItem", true, utils.NonTransactional)
|
|
if _, err := chS.GetWithRemote(args); err == nil || err != utils.ErrNotFound {
|
|
t.Errorf("expected %v,received %v", utils.ErrNotFound, err)
|
|
}
|
|
cfg.DataDbCfg().Items[utils.CacheTBLTPActionPlans].Remote = true
|
|
cfg.CacheCfg().RemoteConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.RemoteConnsCfg)}
|
|
/*
|
|
if _, err = chS.GetWithRemote(args); err == nil || err != utils.ErrNotFound {
|
|
t.Errorf("expected %v,received %v", utils.ErrNotFound, err)
|
|
}
|
|
*/
|
|
}
|
|
|
|
func TestV1LoadCache(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
tmpDm := dm
|
|
defer func() {
|
|
dm = tmpDm
|
|
}()
|
|
attr := &utils.AttrReloadCacheWithAPIOpts{
|
|
Tenant: "cgrates.org",
|
|
FilterIDs: []string{"cgrates.org:FLTR_ID"},
|
|
AttributeFilterIndexIDs: []string{"cgrates.org:*any:*string:*req.Account:1001", "cgrates.org:*any:*string:*req.Account:1002"},
|
|
}
|
|
chS := NewCacheS(cfg, dm, nil)
|
|
var reply string
|
|
if err := chS.V1LoadCache(context.Background(), attr, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("reply should be %v", utils.OK)
|
|
}
|
|
|
|
}
|
|
|
|
func TestCacheSBeginTransaction(t *testing.T) {
|
|
tmp := Cache
|
|
defer func() {
|
|
Cache = tmp
|
|
}()
|
|
Cache.Clear(nil)
|
|
|
|
cfg := config.NewDefaultCGRConfig()
|
|
db, err := NewInternalDB(nil, nil, false, nil, cfg.DataDbCfg().Items)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
dm := NewDataManager(db, cfg.CacheCfg(), nil)
|
|
|
|
cacheS := NewCacheS(cfg, dm, nil)
|
|
|
|
expFormat := `........-....-....-....-............`
|
|
rcv := cacheS.BeginTransaction()
|
|
if matched, err := regexp.Match(expFormat, []byte(rcv)); err != nil {
|
|
t.Error(err)
|
|
} else if !matched {
|
|
t.Errorf("Unexpected transaction format, Received <%v>", rcv)
|
|
}
|
|
|
|
}
|
|
|
|
func TestCachesV1ReLoadCache(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
tmpDm := dm
|
|
defer func() {
|
|
dm = tmpDm
|
|
}()
|
|
attr := &utils.AttrReloadCacheWithAPIOpts{
|
|
Tenant: "cgrates.org",
|
|
FilterIDs: []string{"cgrates.org:FLTR_ID"},
|
|
AttributeFilterIndexIDs: []string{"cgrates.org:*any:*string:*req.Account:1001", "cgrates.org:*any:*string:*req.Account:1002"},
|
|
}
|
|
chS := NewCacheS(cfg, dm, nil)
|
|
var reply string
|
|
if err := chS.V1ReloadCache(context.Background(), attr, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("reply should be %v", utils.OK)
|
|
}
|
|
|
|
}
|