mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Added tests for resources
This commit is contained in:
committed by
Dan Christian Bogos
parent
317586873d
commit
b0c6e59740
@@ -121,16 +121,15 @@ func (ru *ResourceUsage) Clone() (cln *ResourceUsage) {
|
||||
// Resource represents a resource in the system
|
||||
// not thread safe, needs locking at process level
|
||||
type Resource struct {
|
||||
Tenant string
|
||||
ID string
|
||||
Usages map[string]*ResourceUsage
|
||||
TTLIdx []string // holds ordered list of ResourceIDs based on their TTL, empty if feature is disableda
|
||||
lkID string // ID of the lock used when matching the resource
|
||||
prflLkID string // ID of the lock used for the profile
|
||||
ttl *time.Duration // time to leave for this resource, picked up on each Resource initialization out of config
|
||||
tUsage *float64 // sum of all usages
|
||||
dirty *bool // the usages were modified, needs save, *bool so we only save if enabled in config
|
||||
rPrf *ResourceProfile // for ordering purposes
|
||||
Tenant string
|
||||
ID string
|
||||
Usages map[string]*ResourceUsage
|
||||
TTLIdx []string // holds ordered list of ResourceIDs based on their TTL, empty if feature is disableda
|
||||
lkID string // ID of the lock used when matching the resource
|
||||
ttl *time.Duration // time to leave for this resource, picked up on each Resource initialization out of config
|
||||
tUsage *float64 // sum of all usages
|
||||
dirty *bool // the usages were modified, needs save, *bool so we only save if enabled in config
|
||||
rPrf *ResourceProfile // for ordering purposes
|
||||
}
|
||||
|
||||
// resourceLockKey returns the ID used to lock a resource with guardian
|
||||
@@ -362,14 +361,9 @@ func (rs Resources) allocateResource(ru *ResourceUsage, dryRun bool) (alcMessage
|
||||
err = fmt.Errorf("empty configuration for resourceID: %s", r.TenantID())
|
||||
return
|
||||
}
|
||||
if r.rPrf.Limit >= r.TotalUsage()+ru.Units || r.rPrf.Limit == -1 {
|
||||
if alcMessage == "" {
|
||||
if r.rPrf.AllocationMessage != "" {
|
||||
alcMessage = r.rPrf.AllocationMessage
|
||||
} else {
|
||||
alcMessage = r.rPrf.ID
|
||||
}
|
||||
}
|
||||
if alcMessage == utils.EmptyString &&
|
||||
(r.rPrf.Limit >= r.TotalUsage()+ru.Units || r.rPrf.Limit == -1) {
|
||||
alcMessage = utils.FirstNonEmpty(r.rPrf.AllocationMessage, r.rPrf.ID)
|
||||
}
|
||||
}
|
||||
if alcMessage == "" {
|
||||
@@ -493,6 +487,31 @@ func (rS *ResourceService) storeResource(r *Resource) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// storeMatchedResources will store the list of resources based on the StoreInterval
|
||||
func (rS *ResourceService) storeMatchedResources(mtcRLs Resources) (err error) {
|
||||
if rS.cgrcfg.ResourceSCfg().StoreInterval == 0 {
|
||||
return
|
||||
}
|
||||
if rS.cgrcfg.ResourceSCfg().StoreInterval > 0 {
|
||||
rS.srMux.Lock()
|
||||
defer rS.srMux.Unlock()
|
||||
}
|
||||
for _, r := range mtcRLs {
|
||||
if r.dirty != nil {
|
||||
*r.dirty = true // mark it to be saved
|
||||
if rS.cgrcfg.ResourceSCfg().StoreInterval > 0 {
|
||||
rS.storedResources.Add(r.TenantID())
|
||||
continue
|
||||
}
|
||||
if err = rS.storeResource(r); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// processThresholds will pass the event for resource to ThresholdS
|
||||
func (rS *ResourceService) processThresholds(rs Resources, opts map[string]interface{}) (err error) {
|
||||
if len(rS.cgrcfg.ResourceSCfg().ThresholdSConns) == 0 {
|
||||
@@ -545,7 +564,6 @@ func (rS *ResourceService) processThresholds(rs Resources, opts map[string]inter
|
||||
// matchingResourcesForEvent returns ordered list of matching resources which are active by the time of the call
|
||||
func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREvent,
|
||||
evUUID string, usageTTL *time.Duration) (rs Resources, err error) {
|
||||
matchingResources := make(map[string]*Resource)
|
||||
var rIDs utils.StringSet
|
||||
evNm := utils.MapStorage{
|
||||
utils.MetaReq: ev.Event,
|
||||
@@ -583,6 +601,7 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv
|
||||
return
|
||||
}
|
||||
}
|
||||
rs = make(Resources, 0, len(rIDs))
|
||||
for resName := range rIDs {
|
||||
lkPrflID := guardian.Guardian.GuardIDs("",
|
||||
config.CgrConfig().GeneralCfg().LockingTimeout,
|
||||
@@ -594,6 +613,7 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv
|
||||
if err == utils.ErrNotFound {
|
||||
continue
|
||||
}
|
||||
rs.unlock()
|
||||
return
|
||||
}
|
||||
rPrf.lock(lkPrflID)
|
||||
@@ -605,6 +625,7 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv
|
||||
if pass, err := rS.filterS.Pass(tnt, rPrf.FilterIDs,
|
||||
evNm); err != nil {
|
||||
rPrf.unlock()
|
||||
rs.unlock()
|
||||
return nil, err
|
||||
} else if !pass {
|
||||
rPrf.unlock()
|
||||
@@ -616,7 +637,8 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv
|
||||
r, err := rS.dm.GetResource(rPrf.Tenant, rPrf.ID, true, true, "")
|
||||
if err != nil {
|
||||
guardian.Guardian.UnguardIDs(lkID)
|
||||
guardian.Guardian.UnguardIDs(lkPrflID)
|
||||
rPrf.unlock()
|
||||
rs.unlock()
|
||||
return nil, err
|
||||
}
|
||||
r.lock(lkID) // pass the lock into resource so we have it as reference
|
||||
@@ -631,17 +653,12 @@ func (rS *ResourceService) matchingResourcesForEvent(tnt string, ev *utils.CGREv
|
||||
r.ttl = utils.DurationPointer(rPrf.UsageTTL)
|
||||
}
|
||||
r.rPrf = rPrf
|
||||
matchingResources[rPrf.ID] = r
|
||||
rs = append(rs, r)
|
||||
}
|
||||
|
||||
if len(matchingResources) == 0 {
|
||||
if len(rs) == 0 {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
// All good, convert from Map to Slice so we can sort
|
||||
rs = make(Resources, 0, len(matchingResources))
|
||||
for _, r := range matchingResources {
|
||||
rs = append(rs, r)
|
||||
}
|
||||
rs.Sort()
|
||||
for i, r := range rs {
|
||||
if r.rPrf.Blocker && i != len(rs)-1 { // blocker will stop processing and we are not at last index
|
||||
@@ -803,21 +820,8 @@ func (rS *ResourceService) V1AllocateResources(args utils.ArgRSv1ResourceUsage,
|
||||
}
|
||||
|
||||
// index it for storing
|
||||
for _, r := range mtcRLs {
|
||||
if rS.cgrcfg.ResourceSCfg().StoreInterval != 0 && r.dirty != nil {
|
||||
if rS.cgrcfg.ResourceSCfg().StoreInterval == -1 {
|
||||
*r.dirty = true
|
||||
if err = rS.storeResource(r); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
*r.dirty = true // mark it to be saved
|
||||
rS.srMux.Lock()
|
||||
rS.storedResources.Add(r.TenantID())
|
||||
rS.srMux.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
if err = rS.storeMatchedResources(mtcRLs); err != nil {
|
||||
return
|
||||
}
|
||||
if err = rS.processThresholds(mtcRLs, args.APIOpts); err != nil {
|
||||
return
|
||||
@@ -863,7 +867,7 @@ func (rS *ResourceService) V1ReleaseResources(args utils.ArgRSv1ResourceUsage, r
|
||||
var mtcRLs Resources
|
||||
if mtcRLs, err = rS.matchingResourcesForEvent(tnt, args.CGREvent, args.UsageID,
|
||||
args.UsageTTL); err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
defer mtcRLs.unlock()
|
||||
|
||||
@@ -872,24 +876,9 @@ func (rS *ResourceService) V1ReleaseResources(args utils.ArgRSv1ResourceUsage, r
|
||||
}
|
||||
|
||||
// Handle storing
|
||||
if rS.cgrcfg.ResourceSCfg().StoreInterval != -1 {
|
||||
rS.srMux.Lock()
|
||||
defer rS.srMux.Unlock()
|
||||
if err = rS.storeMatchedResources(mtcRLs); err != nil {
|
||||
return
|
||||
}
|
||||
for _, r := range mtcRLs {
|
||||
if r.dirty != nil {
|
||||
if rS.cgrcfg.ResourceSCfg().StoreInterval == -1 {
|
||||
if err = rS.storeResource(r); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
*r.dirty = true // mark it to be saved
|
||||
rS.storedResources.Add(r.TenantID())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err = rS.processThresholds(mtcRLs, args.APIOpts); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2617,166 +2617,18 @@ func TestResourceMatchWithIndexFalse(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResourceCaching(t *testing.T) {
|
||||
var dmRES *DataManager
|
||||
defaultCfg := config.NewDefaultCGRConfig()
|
||||
data := NewInternalDB(nil, nil, true)
|
||||
dmRES = NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
|
||||
defaultCfg.ResourceSCfg().StoreInterval = 1
|
||||
defaultCfg.ResourceSCfg().StringIndexedFields = nil
|
||||
defaultCfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
resService := NewResourceService(dmRES, defaultCfg,
|
||||
&FilterS{dm: dmRES, cfg: defaultCfg}, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
fltrRes1 := &Filter{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "FLTR_RES_1",
|
||||
Rules: []*FilterRule{
|
||||
{
|
||||
Type: utils.MetaString,
|
||||
Element: "~*req.Resources",
|
||||
Values: []string{"ResourceProfile1"},
|
||||
},
|
||||
{
|
||||
Type: utils.MetaGreaterOrEqual,
|
||||
Element: "~*req.UsageInterval",
|
||||
Values: []string{(time.Second).String()},
|
||||
},
|
||||
{
|
||||
Type: utils.MetaGreaterOrEqual,
|
||||
Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.Usage,
|
||||
Values: []string{(time.Second).String()},
|
||||
},
|
||||
{
|
||||
Type: utils.MetaGreaterOrEqual,
|
||||
Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.Weight,
|
||||
Values: []string{"9.0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
dmRES.SetFilter(fltrRes1, true)
|
||||
fltrRes2 := &Filter{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "FLTR_RES_2",
|
||||
Rules: []*FilterRule{
|
||||
{
|
||||
Type: utils.MetaString,
|
||||
Element: "~*req.Resources",
|
||||
Values: []string{"ResourceProfile2"},
|
||||
},
|
||||
{
|
||||
Type: utils.MetaGreaterOrEqual,
|
||||
Element: "~*req.PddInterval",
|
||||
Values: []string{(time.Second).String()},
|
||||
},
|
||||
{
|
||||
Type: utils.MetaGreaterOrEqual,
|
||||
Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.Usage,
|
||||
Values: []string{(time.Second).String()},
|
||||
},
|
||||
{
|
||||
Type: utils.MetaGreaterOrEqual,
|
||||
Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.Weight,
|
||||
Values: []string{"15.0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
dmRES.SetFilter(fltrRes2, true)
|
||||
fltrRes3 := &Filter{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "FLTR_RES_3",
|
||||
Rules: []*FilterRule{
|
||||
{
|
||||
Type: utils.MetaPrefix,
|
||||
Element: "~*req.Resources",
|
||||
Values: []string{"ResourceProfilePrefix"},
|
||||
},
|
||||
},
|
||||
}
|
||||
dmRES.SetFilter(fltrRes3, true)
|
||||
resprf := []*ResourceProfile{
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile1",
|
||||
FilterIDs: []string{"FLTR_RES_1"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{""},
|
||||
},
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile2", // identifier of this resource
|
||||
FilterIDs: []string{"FLTR_RES_2"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{""},
|
||||
},
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile3",
|
||||
FilterIDs: []string{"FLTR_RES_3"},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
|
||||
},
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{""},
|
||||
},
|
||||
}
|
||||
resourceTest := Resources{
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile1",
|
||||
Usages: map[string]*ResourceUsage{},
|
||||
TTLIdx: []string{},
|
||||
rPrf: resprf[0],
|
||||
},
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile2",
|
||||
Usages: map[string]*ResourceUsage{},
|
||||
TTLIdx: []string{},
|
||||
rPrf: resprf[1],
|
||||
},
|
||||
{
|
||||
Tenant: config.CgrConfig().GeneralCfg().DefaultTenant,
|
||||
ID: "ResourceProfile3",
|
||||
Usages: map[string]*ResourceUsage{},
|
||||
TTLIdx: []string{},
|
||||
rPrf: resprf[2],
|
||||
},
|
||||
}
|
||||
|
||||
for _, resProfile := range resprf {
|
||||
dmRES.SetResourceProfile(resProfile, true)
|
||||
}
|
||||
for _, res := range resourceTest {
|
||||
dmRES.SetResource(res)
|
||||
}
|
||||
//clear the cache
|
||||
Cache.Clear(nil)
|
||||
|
||||
// start fresh with new dataManager
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
dm := NewDataManager(NewInternalDB(nil, nil, true), config.CgrConfig().CacheCfg(), nil)
|
||||
|
||||
dmRES = NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
|
||||
|
||||
defaultCfg.ResourceSCfg().StoreInterval = 1
|
||||
defaultCfg.ResourceSCfg().StringIndexedFields = nil
|
||||
defaultCfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
resService = NewResourceService(dmRES, defaultCfg,
|
||||
&FilterS{dm: dmRES, cfg: defaultCfg}, nil)
|
||||
cfg.ResourceSCfg().StoreInterval = 1
|
||||
cfg.ResourceSCfg().StringIndexedFields = nil
|
||||
cfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
rS := NewResourceService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
@@ -2822,7 +2674,7 @@ func TestResourceCaching(t *testing.T) {
|
||||
"Destination": "3002"},
|
||||
}
|
||||
|
||||
mres, err := resService.matchingResourcesForEvent(ev.Tenant, ev,
|
||||
mres, err := rS.matchingResourcesForEvent(ev.Tenant, ev,
|
||||
"TestResourceCaching", nil)
|
||||
if err != nil {
|
||||
t.Errorf("Error: %+v", err)
|
||||
@@ -6304,3 +6156,387 @@ func TestResourcesV1ReleaseResourcesProcessThErr(t *testing.T) {
|
||||
|
||||
dm.DataDB().Flush(utils.EmptyString)
|
||||
}
|
||||
|
||||
func TestResourcesStoreResourceError(t *testing.T) {
|
||||
Cache.Clear(nil)
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
cfg.ResourceSCfg().StoreInterval = -1
|
||||
cfg.RPCConns()["test"] = &config.RPCConn{
|
||||
Conns: []*config.RemoteHost{{}},
|
||||
}
|
||||
cfg.DataDbCfg().RplConns = []string{"test"}
|
||||
dft := config.CgrConfig()
|
||||
config.SetCgrConfig(cfg)
|
||||
defer config.SetCgrConfig(dft)
|
||||
|
||||
db := NewInternalDB(nil, nil, true)
|
||||
dm := NewDataManager(db, cfg.CacheCfg(), NewConnManager(cfg, make(map[string]chan rpcclient.ClientConnector)))
|
||||
|
||||
rS := NewResourceService(dm, cfg, NewFilterS(cfg, nil, dm), nil)
|
||||
|
||||
rsPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "RES1",
|
||||
FilterIDs: []string{"*string:~*req.Account:1001"},
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
AllocationMessage: "Approved",
|
||||
Weight: 10,
|
||||
Limit: 10,
|
||||
UsageTTL: time.Minute,
|
||||
Stored: true,
|
||||
}
|
||||
|
||||
err := dm.SetResourceProfile(rsPrf, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
args := utils.ArgRSv1ResourceUsage{
|
||||
CGREvent: &utils.CGREvent{
|
||||
ID: "EventAuthorizeResource",
|
||||
Event: map[string]interface{}{
|
||||
utils.AccountField: "1001",
|
||||
},
|
||||
},
|
||||
UsageID: "RU_Test",
|
||||
UsageTTL: utils.DurationPointer(time.Minute),
|
||||
Units: 5,
|
||||
}
|
||||
cfg.DataDbCfg().Items[utils.MetaResources].Replicate = true
|
||||
var reply string
|
||||
if err := rS.V1AllocateResources(args, &reply); err != utils.ErrDisconnected {
|
||||
t.Error(err)
|
||||
}
|
||||
cfg.DataDbCfg().Items[utils.MetaResources].Replicate = false
|
||||
|
||||
if err := rS.V1AllocateResources(args, &reply); err != nil {
|
||||
t.Error(err)
|
||||
} else if reply != "Approved" {
|
||||
t.Errorf("Unexpected reply returned: %q", reply)
|
||||
}
|
||||
|
||||
cfg.DataDbCfg().Items[utils.MetaResources].Replicate = true
|
||||
if err := rS.V1ReleaseResources(args, &reply); err != utils.ErrDisconnected {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceMatchingResourcesForEventNotFoundInCache(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
db := NewInternalDB(nil, nil, true)
|
||||
dmRES := NewDataManager(db, config.CgrConfig().CacheCfg(), nil)
|
||||
cfg.ResourceSCfg().StoreInterval = 1
|
||||
cfg.ResourceSCfg().StringIndexedFields = nil
|
||||
cfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
rS := NewResourceService(dmRES, cfg,
|
||||
&FilterS{dm: dmRES, cfg: cfg}, nil)
|
||||
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventNotFoundInCache", nil, nil, true, utils.NonTransactional)
|
||||
_, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
"TestResourceMatchingResourcesForEventNotFoundInCache", utils.DurationPointer(10*time.Second))
|
||||
if err != utils.ErrNotFound {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceMatchingResourcesForEventNotFoundInDB(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
db := NewInternalDB(nil, nil, true)
|
||||
dmRES := NewDataManager(db, config.CgrConfig().CacheCfg(), nil)
|
||||
cfg.ResourceSCfg().StoreInterval = 1
|
||||
cfg.ResourceSCfg().StringIndexedFields = nil
|
||||
cfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
rS := NewResourceService(dmRES, cfg,
|
||||
&FilterS{dm: dmRES, cfg: cfg}, nil)
|
||||
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventNotFoundInDB", utils.StringSet{"Res2": {}}, nil, true, utils.NonTransactional)
|
||||
_, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
"TestResourceMatchingResourcesForEventNotFoundInDB", utils.DurationPointer(10*time.Second))
|
||||
if err != utils.ErrNotFound {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceMatchingResourcesForEventLocks(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
db := NewInternalDB(nil, nil, true)
|
||||
dm := NewDataManager(db, config.CgrConfig().CacheCfg(), nil)
|
||||
cfg.ResourceSCfg().StoreInterval = 1
|
||||
cfg.ResourceSCfg().StringIndexedFields = nil
|
||||
cfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
rS := NewResourceService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
prfs := make([]*ResourceProfile, 0)
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: fmt.Sprintf("RES%d", i),
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
prfs = append(prfs, rPrf)
|
||||
ids.Add(rPrf.ID)
|
||||
}
|
||||
dm.RemoveResource("cgrates.org", "RES1")
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocks", ids, nil, true, utils.NonTransactional)
|
||||
_, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
"TestResourceMatchingResourcesForEventLocks", utils.DurationPointer(10*time.Second))
|
||||
if err != utils.ErrNotFound {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
for _, rPrf := range prfs {
|
||||
if rPrf.isLocked() {
|
||||
t.Fatalf("Expected profile to not be locked %q", rPrf.ID)
|
||||
}
|
||||
if rPrf.ID == "RES1" {
|
||||
continue
|
||||
}
|
||||
if r, err := dm.GetResource(rPrf.Tenant, rPrf.ID, true, false, utils.NonTransactional); err != nil {
|
||||
t.Errorf("error %s for <%s>", err, rPrf.ID)
|
||||
} else if r.isLocked() {
|
||||
t.Fatalf("Expected resource to not be locked %q", rPrf.ID)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestResourceMatchingResourcesForEventLocks2(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
db := NewInternalDB(nil, nil, true)
|
||||
dm := NewDataManager(db, config.CgrConfig().CacheCfg(), nil)
|
||||
cfg.ResourceSCfg().StoreInterval = 1
|
||||
cfg.ResourceSCfg().StringIndexedFields = nil
|
||||
cfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
rS := NewResourceService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
prfs := make([]*ResourceProfile, 0)
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: fmt.Sprintf("RES%d", i),
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
prfs = append(prfs, rPrf)
|
||||
ids.Add(rPrf.ID)
|
||||
}
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "RES20",
|
||||
FilterIDs: []string{"FLTR_RES_201"},
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
}
|
||||
err = db.SetResourceProfileDrv(rPrf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
prfs = append(prfs, rPrf)
|
||||
ids.Add(rPrf.ID)
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocks2", ids, nil, true, utils.NonTransactional)
|
||||
_, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
"TestResourceMatchingResourcesForEventLocks2", utils.DurationPointer(10*time.Second))
|
||||
expErr := utils.ErrPrefixNotFound(rPrf.FilterIDs[0])
|
||||
if err == nil || err.Error() != expErr.Error() {
|
||||
t.Errorf("Expected error: %s ,received: %+v", expErr, err)
|
||||
}
|
||||
for _, rPrf := range prfs {
|
||||
if rPrf.isLocked() {
|
||||
t.Fatalf("Expected profile to not be locked %q", rPrf.ID)
|
||||
}
|
||||
if rPrf.ID == "RES20" {
|
||||
continue
|
||||
}
|
||||
if r, err := dm.GetResource(rPrf.Tenant, rPrf.ID, true, false, utils.NonTransactional); err != nil {
|
||||
t.Errorf("error %s for <%s>", err, rPrf.ID)
|
||||
} else if r.isLocked() {
|
||||
t.Fatalf("Expected resource to not be locked %q", rPrf.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceMatchingResourcesForEventLocksBlocker(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
db := NewInternalDB(nil, nil, true)
|
||||
dm := NewDataManager(db, config.CgrConfig().CacheCfg(), nil)
|
||||
cfg.ResourceSCfg().StoreInterval = 1
|
||||
cfg.ResourceSCfg().StringIndexedFields = nil
|
||||
cfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
rS := NewResourceService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
prfs := make([]*ResourceProfile, 0)
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: fmt.Sprintf("RES%d", i),
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: float64(10 - i),
|
||||
Blocker: i == 4,
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
prfs = append(prfs, rPrf)
|
||||
ids.Add(rPrf.ID)
|
||||
}
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocksBlocker", ids, nil, true, utils.NonTransactional)
|
||||
mres, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
"TestResourceMatchingResourcesForEventLocksBlocker", utils.DurationPointer(10*time.Second))
|
||||
if err != nil {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
defer mres.unlock()
|
||||
if len(mres) != 5 {
|
||||
t.Fatal("Expected 6 resources")
|
||||
}
|
||||
for _, rPrf := range prfs[5:] {
|
||||
if rPrf.isLocked() {
|
||||
t.Errorf("Expected profile to not be locked %q", rPrf.ID)
|
||||
}
|
||||
if r, err := dm.GetResource(rPrf.Tenant, rPrf.ID, true, false, utils.NonTransactional); err != nil {
|
||||
t.Errorf("error %s for <%s>", err, rPrf.ID)
|
||||
} else if r.isLocked() {
|
||||
t.Fatalf("Expected resource to not be locked %q", rPrf.ID)
|
||||
}
|
||||
}
|
||||
for _, rPrf := range prfs[:5] {
|
||||
if !rPrf.isLocked() {
|
||||
t.Errorf("Expected profile to be locked %q", rPrf.ID)
|
||||
}
|
||||
if r, err := dm.GetResource(rPrf.Tenant, rPrf.ID, true, false, utils.NonTransactional); err != nil {
|
||||
t.Errorf("error %s for <%s>", err, rPrf.ID)
|
||||
} else if !r.isLocked() {
|
||||
t.Fatalf("Expected resource to be locked %q", rPrf.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceMatchingResourcesForEventLocksActivationInterval(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
db := NewInternalDB(nil, nil, true)
|
||||
dm := NewDataManager(db, config.CgrConfig().CacheCfg(), nil)
|
||||
cfg.ResourceSCfg().StoreInterval = 1
|
||||
cfg.ResourceSCfg().StringIndexedFields = nil
|
||||
cfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
rS := NewResourceService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: fmt.Sprintf("RES%d", i),
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
ids.Add(rPrf.ID)
|
||||
}
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: "RES21",
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ExpiryTime: time.Now().Add(-5 * time.Second),
|
||||
},
|
||||
}
|
||||
dm.SetResourceProfile(rPrf, true)
|
||||
ids.Add(rPrf.ID)
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocks2", ids, nil, true, utils.NonTransactional)
|
||||
mres, err := rS.matchingResourcesForEvent("cgrates.org", &utils.CGREvent{Time: utils.TimePointer(time.Now())},
|
||||
"TestResourceMatchingResourcesForEventLocks2", utils.DurationPointer(10*time.Second))
|
||||
if err != nil {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
defer mres.unlock()
|
||||
if rPrf.isLocked() {
|
||||
t.Fatalf("Expected profile to not be locked %q", rPrf.ID)
|
||||
}
|
||||
if r, err := dm.GetResource(rPrf.Tenant, rPrf.ID, true, false, utils.NonTransactional); err != nil {
|
||||
t.Errorf("error %s for <%s>", err, rPrf.ID)
|
||||
} else if r.isLocked() {
|
||||
t.Fatalf("Expected resource to not be locked %q", rPrf.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceMatchingResourcesForEventLocks3(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
prfs := make([]*ResourceProfile, 0)
|
||||
Cache.Clear(nil)
|
||||
db := &DataDBMock{
|
||||
GetResourceProfileDrvF: func(tnt, id string) (*ResourceProfile, error) {
|
||||
if id == "RES1" {
|
||||
return nil, utils.ErrNotImplemented
|
||||
}
|
||||
rPrf := &ResourceProfile{
|
||||
Tenant: "cgrates.org",
|
||||
ID: id,
|
||||
UsageTTL: 10 * time.Second,
|
||||
Limit: 10.00,
|
||||
AllocationMessage: "AllocationMessage",
|
||||
Weight: 20.00,
|
||||
ThresholdIDs: []string{utils.MetaNone},
|
||||
}
|
||||
Cache.Set(utils.CacheResources, rPrf.TenantID(), &Resource{
|
||||
Tenant: rPrf.Tenant,
|
||||
ID: rPrf.ID,
|
||||
Usages: make(map[string]*ResourceUsage),
|
||||
}, nil, true, utils.NonTransactional)
|
||||
prfs = append(prfs, rPrf)
|
||||
return rPrf, nil
|
||||
},
|
||||
}
|
||||
dm := NewDataManager(db, config.CgrConfig().CacheCfg(), nil)
|
||||
cfg.ResourceSCfg().StoreInterval = 1
|
||||
cfg.ResourceSCfg().StringIndexedFields = nil
|
||||
cfg.ResourceSCfg().PrefixIndexedFields = nil
|
||||
rS := NewResourceService(dm, cfg,
|
||||
&FilterS{dm: dm, cfg: cfg}, nil)
|
||||
|
||||
ids := utils.StringSet{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ids.Add(fmt.Sprintf("RES%d", i))
|
||||
}
|
||||
Cache.Set(utils.CacheEventResources, "TestResourceMatchingResourcesForEventLocks3", ids, nil, true, utils.NonTransactional)
|
||||
_, err := rS.matchingResourcesForEvent("cgrates.org", new(utils.CGREvent),
|
||||
"TestResourceMatchingResourcesForEventLocks3", utils.DurationPointer(10*time.Second))
|
||||
if err != utils.ErrNotImplemented {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
for _, rPrf := range prfs {
|
||||
if rPrf.isLocked() {
|
||||
t.Fatalf("Expected profile to not be locked %q", rPrf.ID)
|
||||
}
|
||||
// if r, err := dm.GetResource(rPrf.Tenant, rPrf.ID, true, false, utils.NonTransactional); err != nil {
|
||||
// t.Errorf("error %s for <%s>", err, rPrf.ID)
|
||||
// } else if r.isLocked() {
|
||||
// t.Fatalf("Expected resource to not be locked %q", rPrf.ID)
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user