mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
288 lines
10 KiB
Go
288 lines
10 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 v1
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/cgrates/birpc"
|
|
"github.com/cgrates/birpc/context"
|
|
"github.com/cgrates/cgrates/config"
|
|
"github.com/cgrates/cgrates/engine"
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
func TestComposeArgsReload(t *testing.T) {
|
|
apv1 := &APIerSv1{}
|
|
expArgs := map[string][]string{utils.CacheAttributeProfiles: {"cgrates.org:ATTR1"}}
|
|
|
|
if rply, err := apv1.composeArgsReload("cgrates.org", utils.CacheAttributeProfiles,
|
|
"cgrates.org:ATTR1", nil, nil); err != nil {
|
|
t.Fatal(err)
|
|
} else if !reflect.DeepEqual(expArgs, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(expArgs), utils.ToJSON(rply))
|
|
}
|
|
|
|
expArgs[utils.CacheAttributeFilterIndexes] = []string{"cgrates.org:*cdrs:*none:*any:*any"}
|
|
|
|
if rply, err := apv1.composeArgsReload("cgrates.org", utils.CacheAttributeProfiles,
|
|
"cgrates.org:ATTR1", &[]string{}, []string{utils.MetaCDRs}); err != nil {
|
|
t.Fatal(err)
|
|
} else if !reflect.DeepEqual(expArgs, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(expArgs), utils.ToJSON(rply))
|
|
}
|
|
|
|
expArgs[utils.CacheAttributeFilterIndexes] = []string{
|
|
"cgrates.org:*cdrs:*string:*req.Account:1001",
|
|
"cgrates.org:*cdrs:*prefix:*req.Destination:1001",
|
|
}
|
|
|
|
if rply, err := apv1.composeArgsReload("cgrates.org", utils.CacheAttributeProfiles,
|
|
"cgrates.org:ATTR1", &[]string{"*string:~*req.Account:1001|~req.Subject", "*prefix:1001:~*req.Destination", "*gt:~req.Usage:0"}, []string{utils.MetaCDRs}); err != nil {
|
|
t.Fatal(err)
|
|
} else if !reflect.DeepEqual(expArgs, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(expArgs), utils.ToJSON(rply))
|
|
}
|
|
|
|
expArgs = map[string][]string{
|
|
utils.CacheStatQueueProfiles: {"cgrates.org:Stat2"},
|
|
utils.CacheStatQueues: {"cgrates.org:Stat2"},
|
|
utils.CacheStatFilterIndexes: {
|
|
"cgrates.org:*string:*req.Account:1001",
|
|
"cgrates.org:*prefix:*req.Destination:1001",
|
|
},
|
|
}
|
|
|
|
if rply, err := apv1.composeArgsReload("cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", &[]string{"*string:~*req.Account:1001|~req.Subject", "*prefix:1001:~*req.Destination"}, nil); err != nil {
|
|
t.Fatal(err)
|
|
} else if !reflect.DeepEqual(expArgs, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(expArgs), utils.ToJSON(rply))
|
|
}
|
|
|
|
expArgs[utils.CacheStatFilterIndexes] = []string{"cgrates.org:*none:*any:*any"}
|
|
|
|
if rply, err := apv1.composeArgsReload("cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", &[]string{}, []string{utils.MetaCDRs}); err != nil {
|
|
t.Fatal(err)
|
|
} else if !reflect.DeepEqual(expArgs, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(expArgs), utils.ToJSON(rply))
|
|
}
|
|
|
|
if _, err := apv1.composeArgsReload("cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", &[]string{"FLTR1"}, []string{utils.MetaCDRs}); err != utils.ErrNoDatabaseConn {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
type rpcRequest struct {
|
|
Method string
|
|
Params any
|
|
}
|
|
type rpcMock chan *rpcRequest
|
|
|
|
func (r rpcMock) Call(_ *context.Context, method string, args, _ any) error {
|
|
r <- &rpcRequest{
|
|
Method: method,
|
|
Params: args,
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestCallCache(t *testing.T) {
|
|
cache := make(rpcMock, 1)
|
|
ch := make(chan birpc.ClientConnector, 1)
|
|
ch <- cache
|
|
cn := engine.NewConnManager(config.CgrConfig(), map[string]chan birpc.ClientConnector{
|
|
utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches): ch,
|
|
})
|
|
cn.Reload()
|
|
apv1 := &APIerSv1{
|
|
ConnMgr: cn,
|
|
Config: config.CgrConfig(),
|
|
}
|
|
if err := apv1.CallCache(utils.MetaNone, "", "", "", utils.EmptyString, nil, nil, nil); err != nil {
|
|
t.Fatal(err)
|
|
} else if len(cache) != 0 {
|
|
t.Fatal("Expected call cache to not be called")
|
|
}
|
|
exp := &rpcRequest{
|
|
Method: utils.CacheSv1Clear,
|
|
Params: &utils.AttrCacheIDsWithAPIOpts{
|
|
Tenant: "cgrates.org",
|
|
CacheIDs: []string{utils.CacheStatQueueProfiles, utils.CacheStatFilterIndexes, utils.CacheStatQueues},
|
|
APIOpts: make(map[string]any),
|
|
},
|
|
}
|
|
if err := apv1.CallCache(utils.MetaClear, "cgrates.org", utils.CacheStatQueueProfiles, "", utils.EmptyString, nil, nil, make(map[string]any)); err != nil {
|
|
t.Fatal(err)
|
|
} else if len(cache) != 1 {
|
|
t.Fatal("Expected call cache to be called")
|
|
} else if rply := <-cache; !reflect.DeepEqual(exp, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(exp), utils.ToJSON(rply))
|
|
}
|
|
|
|
exp = &rpcRequest{
|
|
Method: utils.CacheSv1ReloadCache,
|
|
Params: &utils.AttrReloadCacheWithAPIOpts{
|
|
APIOpts: make(map[string]any),
|
|
Tenant: "cgrates.org",
|
|
StatsQueueProfileIDs: []string{"cgrates.org:Stat2"},
|
|
StatsQueueIDs: []string{"cgrates.org:Stat2"},
|
|
StatFilterIndexIDs: []string{
|
|
"cgrates.org:*string:*req.Account:1001",
|
|
"cgrates.org:*prefix:*req.Destination:1001",
|
|
},
|
|
},
|
|
}
|
|
|
|
if err := apv1.CallCache(utils.MetaReload, "cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", utils.EmptyString, &[]string{"*string:~*req.Account:1001|~req.Subject", "*prefix:1001:~*req.Destination"},
|
|
nil, make(map[string]any)); err != nil {
|
|
t.Fatal(err)
|
|
} else if len(cache) != 1 {
|
|
t.Fatal("Expected call cache to be called")
|
|
} else if rply := <-cache; !reflect.DeepEqual(exp, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(exp), utils.ToJSON(rply))
|
|
}
|
|
exp.Method = utils.CacheSv1LoadCache
|
|
if err := apv1.CallCache(utils.MetaLoad, "cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", utils.EmptyString, &[]string{"*string:~*req.Account:1001|~req.Subject", "*prefix:1001:~*req.Destination"},
|
|
nil, make(map[string]any)); err != nil {
|
|
t.Fatal(err)
|
|
} else if len(cache) != 1 {
|
|
t.Fatal("Expected call cache to be called")
|
|
} else if rply := <-cache; !reflect.DeepEqual(exp, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(exp), utils.ToJSON(rply))
|
|
}
|
|
exp.Method = utils.CacheSv1RemoveItems
|
|
if err := apv1.CallCache(utils.MetaRemove, "cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", utils.EmptyString, &[]string{"*string:~*req.Account:1001|~req.Subject", "*prefix:1001:~*req.Destination"},
|
|
nil, make(map[string]any)); err != nil {
|
|
t.Fatal(err)
|
|
} else if len(cache) != 1 {
|
|
t.Fatal("Expected call cache to be called")
|
|
} else if rply := <-cache; !reflect.DeepEqual(exp, rply) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(exp), utils.ToJSON(rply))
|
|
}
|
|
|
|
if err := apv1.CallCache(utils.MetaLoad, "cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", utils.EmptyString, &[]string{"FLTR1", "*prefix:1001:~*req.Destination"},
|
|
nil, make(map[string]any)); err != utils.ErrNoDatabaseConn {
|
|
t.Fatal(err)
|
|
} else if len(cache) != 0 {
|
|
t.Fatal("Expected call cache to not be called")
|
|
}
|
|
if err := apv1.CallCache(utils.MetaRemove, "cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", utils.EmptyString, &[]string{"FLTR1", "*prefix:1001:~*req.Destination"},
|
|
nil, make(map[string]any)); err != utils.ErrNoDatabaseConn {
|
|
t.Fatal(err)
|
|
} else if len(cache) != 0 {
|
|
t.Fatal("Expected call cache to not be called")
|
|
}
|
|
if err := apv1.CallCache(utils.MetaReload, "cgrates.org", utils.CacheStatQueueProfiles,
|
|
"cgrates.org:Stat2", utils.EmptyString, &[]string{"FLTR1", "*prefix:1001:~*req.Destination"},
|
|
nil, make(map[string]any)); err != utils.ErrNoDatabaseConn {
|
|
t.Fatal(err)
|
|
} else if len(cache) != 0 {
|
|
t.Fatal("Expected call cache to not be called")
|
|
}
|
|
}
|
|
|
|
func TestCallCacheForFilter(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
idb, err := engine.NewInternalDB(nil, nil, true, nil, cfg.DataDbCfg().Items)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
dm := engine.NewDataManager(idb, cfg.CacheCfg(), nil)
|
|
tnt := "cgrates.org"
|
|
flt := &engine.Filter{
|
|
Tenant: tnt,
|
|
ID: "FLTR1",
|
|
Rules: []*engine.FilterRule{{
|
|
Type: utils.MetaString,
|
|
Element: "~*req.Account",
|
|
Values: []string{"1001"},
|
|
}},
|
|
}
|
|
if err := flt.Compile(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := dm.SetFilter(flt, true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
th := &engine.ThresholdProfile{
|
|
Tenant: tnt,
|
|
ID: "TH1",
|
|
FilterIDs: []string{flt.ID},
|
|
}
|
|
if err := dm.SetThresholdProfile(th, true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
attr := &engine.AttributeProfile{
|
|
Tenant: tnt,
|
|
ID: "Attr1",
|
|
Contexts: []string{utils.MetaAny},
|
|
FilterIDs: []string{flt.ID},
|
|
}
|
|
if err := dm.SetAttributeProfile(attr, true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
exp := map[string][]string{
|
|
utils.CacheFilters: {"cgrates.org:FLTR1"},
|
|
utils.CacheAttributeFilterIndexes: {"cgrates.org:*any:*string:*req.Account:1001"},
|
|
utils.CacheThresholdFilterIndexes: {"cgrates.org:*string:*req.Account:1001"},
|
|
}
|
|
rpl, err := composeCacheArgsForFilter(dm, flt, tnt, flt.TenantID(), map[string][]string{utils.CacheFilters: {"cgrates.org:FLTR1"}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else if !reflect.DeepEqual(rpl, exp) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(exp), utils.ToJSON(rpl))
|
|
}
|
|
flt = &engine.Filter{
|
|
Tenant: tnt,
|
|
ID: "FLTR1",
|
|
Rules: []*engine.FilterRule{{
|
|
Type: utils.MetaString,
|
|
Element: "~*req.Account",
|
|
Values: []string{"1002"},
|
|
}},
|
|
}
|
|
if err := flt.Compile(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := dm.SetFilter(flt, true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
exp = map[string][]string{
|
|
utils.CacheFilters: {"cgrates.org:FLTR1"},
|
|
utils.CacheAttributeFilterIndexes: {"cgrates.org:*any:*string:*req.Account:1001", "cgrates.org:*any:*string:*req.Account:1002"},
|
|
utils.CacheThresholdFilterIndexes: {"cgrates.org:*string:*req.Account:1001", "cgrates.org:*string:*req.Account:1002"},
|
|
}
|
|
rpl, err = composeCacheArgsForFilter(dm, flt, tnt, flt.TenantID(), rpl)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else if !reflect.DeepEqual(rpl, exp) {
|
|
t.Errorf("Expected %s ,received: %s", utils.ToJSON(exp), utils.ToJSON(rpl))
|
|
}
|
|
}
|