mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-20 14:48:43 +05:00
Reslimiter tests
This commit is contained in:
@@ -286,7 +286,7 @@ func (rls *ResourceLimiterService) V1AllowUsage(args utils.AttrRLsResourceUsage,
|
||||
return utils.NewErrServerError(err)
|
||||
}
|
||||
if _, err = mtcRLs.AllocateResource(&ResourceUsage{ID: args.UsageID,
|
||||
Time: time.Now(), Units: args.Units}, false); err != nil {
|
||||
Time: time.Now(), Units: args.Units}, true); err != nil {
|
||||
if err == utils.ErrResourceUnavailable {
|
||||
return // not error but still not allowed
|
||||
}
|
||||
|
||||
@@ -18,409 +18,276 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
// "reflect"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
var rLS *ResourceLimiterService
|
||||
var (
|
||||
rl, rl2 *ResourceLimit
|
||||
ru, ru2, ru3 *ResourceUsage
|
||||
rls ResourceLimits
|
||||
)
|
||||
|
||||
/*
|
||||
func TestRLsIndexStringFilters(t *testing.T) {
|
||||
rls := []*ResourceLimit{
|
||||
&ResourceLimit{
|
||||
ID: "RL1",
|
||||
Weight: 20,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"1001", "1002"}},
|
||||
&RequestFilter{Type: MetaRSRFields, Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
|
||||
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
|
||||
}},
|
||||
ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Limit: 2,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL2",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"dan", "1002"}},
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan"}},
|
||||
},
|
||||
ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Limit: 1,
|
||||
UsageTTL: time.Duration(1 * time.Millisecond),
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL4",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaStringPrefix, FieldName: "Destination", Values: []string{"+49"}},
|
||||
},
|
||||
ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Limit: 1,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL5",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaStringPrefix, FieldName: "Destination", Values: []string{"+40"}},
|
||||
},
|
||||
ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Limit: 1,
|
||||
UsageTTL: time.Duration(10 * time.Millisecond),
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
func TestResourceLimitRecordUsage(t *testing.T) {
|
||||
ru = &ResourceUsage{
|
||||
ID: "RU1",
|
||||
Time: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Units: 2,
|
||||
}
|
||||
for _, rl := range rls {
|
||||
cache.Set(utils.ResourceLimitsPrefix+rl.ID, rl, true, "")
|
||||
|
||||
ru2 = &ResourceUsage{
|
||||
ID: "RU2",
|
||||
Time: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Units: 2,
|
||||
}
|
||||
rLS = new(ResourceLimiterService)
|
||||
eIndexes := map[string]map[string]utils.StringMap{
|
||||
"Account": map[string]utils.StringMap{
|
||||
"1001": utils.StringMap{
|
||||
"RL1": true,
|
||||
},
|
||||
"1002": utils.StringMap{
|
||||
"RL1": true,
|
||||
"RL2": true,
|
||||
},
|
||||
"dan": utils.StringMap{
|
||||
"RL2": true,
|
||||
},
|
||||
},
|
||||
"Subject": map[string]utils.StringMap{
|
||||
"dan": utils.StringMap{
|
||||
"RL2": true,
|
||||
},
|
||||
},
|
||||
utils.NOT_AVAILABLE: map[string]utils.StringMap{
|
||||
utils.NOT_AVAILABLE: utils.StringMap{
|
||||
"RL4": true,
|
||||
"RL5": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := rLS.indexStringFilters(nil); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eIndexes, rLS.stringIndexes) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eIndexes, rLS.stringIndexes)
|
||||
}
|
||||
rl3 := &ResourceLimit{
|
||||
ID: "RL3",
|
||||
Weight: 10,
|
||||
|
||||
rl = &ResourceLimit{
|
||||
ID: "RL1",
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan"}},
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"1003"}},
|
||||
},
|
||||
ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Limit: 1,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
}
|
||||
cache.Set(utils.ResourceLimitsPrefix+rl3.ID, rl3, true, "")
|
||||
rl6 := &ResourceLimit{ // Add it so we can test expiryTime
|
||||
ID: "RL6",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan"}},
|
||||
},
|
||||
ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
ExpiryTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Limit: 1,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
}
|
||||
cache.Set(utils.ResourceLimitsPrefix+rl6.ID, rl6, true, "")
|
||||
eIndexes = map[string]map[string]utils.StringMap{
|
||||
"Account": map[string]utils.StringMap{
|
||||
"1001": utils.StringMap{
|
||||
"RL1": true,
|
||||
&RequestFilter{
|
||||
Type: MetaString,
|
||||
FieldName: "Account",
|
||||
Values: []string{"1001", "1002"},
|
||||
},
|
||||
"1002": utils.StringMap{
|
||||
"RL1": true,
|
||||
"RL2": true,
|
||||
},
|
||||
"dan": utils.StringMap{
|
||||
"RL2": true,
|
||||
&RequestFilter{
|
||||
Type: MetaRSRFields,
|
||||
Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
|
||||
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
|
||||
},
|
||||
},
|
||||
"Subject": map[string]utils.StringMap{
|
||||
"dan": utils.StringMap{
|
||||
"RL2": true,
|
||||
"RL3": true,
|
||||
"RL6": true,
|
||||
},
|
||||
"1003": utils.StringMap{
|
||||
"RL3": true,
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
},
|
||||
ExpiryTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Weight: 100,
|
||||
Limit: 2,
|
||||
ActionTriggers: ActionTriggers{
|
||||
&ActionTrigger{
|
||||
// ID string // original csv tag
|
||||
// UniqueID string // individual id
|
||||
ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
|
||||
ThresholdValue: 2,
|
||||
// Recurrent bool // reset excuted flag each run
|
||||
// MinSleep time.Duration // Minimum duration between two executions in case of recurrent triggers
|
||||
// ExpirationDate time.Time
|
||||
// ActivationDate time.Time
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
},
|
||||
ActionsID: "TEST_ACTIONS",
|
||||
// Weight float64
|
||||
// ActionsID string
|
||||
// MinQueuedItems int // Trigger actions only if this number is hit (stats only)
|
||||
// Executed bool
|
||||
// LastExecutionTime time.Time
|
||||
},
|
||||
},
|
||||
utils.NOT_AVAILABLE: map[string]utils.StringMap{
|
||||
utils.NOT_AVAILABLE: utils.StringMap{
|
||||
"RL4": true,
|
||||
"RL5": true,
|
||||
},
|
||||
UsageTTL: time.Duration(1 * time.Millisecond),
|
||||
AllocationMessage: "ALLOC",
|
||||
Usage: map[string]*ResourceUsage{
|
||||
ru.ID: ru,
|
||||
},
|
||||
TotalUsage: 2,
|
||||
}
|
||||
// Test index update
|
||||
if err := rLS.indexStringFilters([]string{rl3.ID, rl6.ID}); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eIndexes, rLS.stringIndexes) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eIndexes, rLS.stringIndexes)
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
func TestResourceLimitsAllowUsage(t *testing.T) {
|
||||
rls := make(ResourceLimits, 0)
|
||||
if !rls.AllowUsage(1.0) {
|
||||
t.Error("Not allowed for empty limits")
|
||||
}
|
||||
rls = ResourceLimits{
|
||||
&ResourceLimit{
|
||||
ID: "RLAU1",
|
||||
Weight: 20,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"1001", "1002"}},
|
||||
&RequestFilter{Type: MetaRSRFields, Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
|
||||
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
|
||||
}},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 1,
|
||||
Usage: map[string]*ResourceUsage{"call1": &ResourceUsage{
|
||||
ID: "call1", UsageTime: time.Now(), UsageUnits: 1}},
|
||||
TotalUsage: 1,
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RLAU2",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"dan", "1002"}},
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan"}},
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 2,
|
||||
UsageTTL: time.Duration(1 * time.Millisecond),
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
}
|
||||
if !rls.AllowUsage(2.0) {
|
||||
t.Error("Not allowed")
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func TestRLsLoadRLs(t *testing.T) {
|
||||
rls := []*ResourceLimit{
|
||||
&ResourceLimit{
|
||||
ID: "RL1",
|
||||
Weight: 20,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"1001", "1002"}},
|
||||
&RequestFilter{Type: MetaRSRFields, Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
|
||||
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
|
||||
}},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 2,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL2",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"dan", "1002"}},
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan"}},
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 1,
|
||||
UsageTTL: time.Duration(1 * time.Millisecond),
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL3",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan2"}},
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"1003"}},
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 1,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL4",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaStringPrefix, FieldName: "Destination", Values: []string{"+49"}},
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 1,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL5",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaStringPrefix, FieldName: "Destination", Values: []string{"+40"}},
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 1,
|
||||
UsageTTL: time.Duration(10 * time.Millisecond),
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{ // Add it so we can test expiryTime
|
||||
ID: "RL6",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan2"}},
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
ExpiryTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Limit: 1,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
}
|
||||
rlIdxr, err := NewReqFilterIndexer(dataStorage, utils.ResourceLimitsIndex)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
for _, rl := range rls {
|
||||
if err := dataStorage.SetResourceLimit(rl, utils.NonTransactional); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rlIdxr.IndexFilters(rl.ID, rl.Filters)
|
||||
}
|
||||
if err := rlIdxr.StoreIndexes(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRLsMatchingResourceLimitsForEvent(t *testing.T) {
|
||||
rLS = &ResourceLimiterService{dataDB: dataStorage, cdrStatS: nil}
|
||||
eResLimits := ResourceLimits{
|
||||
&ResourceLimit{
|
||||
ID: "RL1",
|
||||
Weight: 20,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"1001", "1002"}},
|
||||
&RequestFilter{Type: MetaRSRFields, Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
|
||||
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
|
||||
}},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 2,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL2",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"dan", "1002"}},
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan"}},
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 1,
|
||||
UsageTTL: time.Duration(1 * time.Millisecond),
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
}
|
||||
if resLimits, err := rLS.matchingResourceLimitsForEvent(
|
||||
map[string]interface{}{"Account": "1002", "Subject": "dan", "Destination": "1002"}); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eResLimits[0].Filters[0], resLimits[0].Filters[0]) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eResLimits, resLimits)
|
||||
if err := rl.RecordUsage(ru2); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else {
|
||||
// Make sure the filters are what we expect to be after retrieving from cache:
|
||||
fltr := resLimits[0].Filters[1]
|
||||
if pass, _ := fltr.Pass(map[string]interface{}{"Subject": "10000001"}, "", nil); !pass {
|
||||
t.Errorf("Expecting RL: %+v, received: %+v", eResLimits[0], resLimits[0])
|
||||
if err := rl.RecordUsage(ru); err == nil {
|
||||
t.Error("Duplicate ResourceUsage id should not be allowed")
|
||||
}
|
||||
if pass, _ := fltr.Pass(map[string]interface{}{"Account": "1002"}, "", nil); pass {
|
||||
t.Errorf("Expecting RL: %+v, received: %+v", eResLimits[0], resLimits[0])
|
||||
if _, found := rl.Usage[ru2.ID]; !found {
|
||||
t.Error("ResourceUsage was not recorded")
|
||||
}
|
||||
if rl.TotalUsage != 4 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 4, rl.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestRLClearUsage(t *testing.T) {
|
||||
rl.Usage = map[string]*ResourceUsage{
|
||||
ru.ID: ru,
|
||||
}
|
||||
rl.TotalUsage = 3
|
||||
|
||||
rl.ClearUsage(ru.ID)
|
||||
|
||||
if len(rl.Usage) != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, len(rl.Usage))
|
||||
}
|
||||
if rl.TotalUsage != 1 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 1, rl.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRLsV1ResourceLimitsForEvent(t *testing.T) {
|
||||
eLimits := []*ResourceLimit{
|
||||
&ResourceLimit{
|
||||
ID: "RL1",
|
||||
Weight: 20,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"1001", "1002"}},
|
||||
&RequestFilter{Type: MetaRSRFields, Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
|
||||
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
|
||||
}},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 2,
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
&ResourceLimit{
|
||||
ID: "RL2",
|
||||
Weight: 10,
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{Type: MetaString, FieldName: "Account", Values: []string{"dan", "1002"}},
|
||||
&RequestFilter{Type: MetaString, FieldName: "Subject", Values: []string{"dan"}},
|
||||
func TestRLRemoveExpiredUnits(t *testing.T) {
|
||||
rl.Usage = map[string]*ResourceUsage{
|
||||
ru.ID: ru,
|
||||
}
|
||||
rl.TotalUsage = 2
|
||||
|
||||
rl.removeExpiredUnits()
|
||||
|
||||
if len(rl.Usage) != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, len(rl.Usage))
|
||||
}
|
||||
if rl.TotalUsage != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, rl.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRLUsedUnits(t *testing.T) {
|
||||
rl.Usage = map[string]*ResourceUsage{
|
||||
ru.ID: ru,
|
||||
}
|
||||
rl.TotalUsage = 2
|
||||
|
||||
usedUnits := rl.UsedUnits()
|
||||
|
||||
if len(rl.Usage) != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, len(rl.Usage))
|
||||
}
|
||||
if usedUnits != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, usedUnits)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRLSort(t *testing.T) {
|
||||
rl2 = &ResourceLimit{
|
||||
ID: "RL2",
|
||||
Filters: []*RequestFilter{
|
||||
&RequestFilter{
|
||||
Type: MetaString,
|
||||
FieldName: "Account",
|
||||
Values: []string{"1001", "1002"},
|
||||
},
|
||||
&RequestFilter{
|
||||
Type: MetaRSRFields,
|
||||
Values: []string{"Subject(~^1.*1$)", "Destination(1002)"},
|
||||
rsrFields: utils.ParseRSRFieldsMustCompile("Subject(~^1.*1$);Destination(1002)", utils.INFIELD_SEP),
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC)},
|
||||
Limit: 1,
|
||||
UsageTTL: time.Duration(1 * time.Millisecond),
|
||||
Usage: make(map[string]*ResourceUsage),
|
||||
},
|
||||
ActivationInterval: &utils.ActivationInterval{
|
||||
ActivationTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
},
|
||||
ExpiryTime: time.Date(2014, 7, 3, 13, 43, 0, 1, time.UTC),
|
||||
Weight: 50,
|
||||
Limit: 2,
|
||||
ActionTriggers: ActionTriggers{
|
||||
&ActionTrigger{
|
||||
// ID string // original csv tag
|
||||
// UniqueID string // individual id
|
||||
ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER,
|
||||
ThresholdValue: 2,
|
||||
// Recurrent bool // reset excuted flag each run
|
||||
// MinSleep time.Duration // Minimum duration between two executions in case of recurrent triggers
|
||||
// ExpirationDate time.Time
|
||||
// ActivationDate time.Time
|
||||
Balance: &BalanceFilter{
|
||||
Type: utils.StringPointer(utils.MONETARY),
|
||||
Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
|
||||
},
|
||||
ActionsID: "TEST_ACTIONS",
|
||||
// Weight float64
|
||||
// ActionsID string
|
||||
// MinQueuedItems int // Trigger actions only if this number is hit (stats only)
|
||||
// Executed bool
|
||||
// LastExecutionTime time.Time
|
||||
},
|
||||
},
|
||||
UsageTTL: time.Duration(1 * time.Millisecond),
|
||||
// AllocationMessage: "ALLOC2",
|
||||
Usage: map[string]*ResourceUsage{
|
||||
ru2.ID: ru2,
|
||||
},
|
||||
TotalUsage: 2,
|
||||
}
|
||||
var rcvLmts []*ResourceLimit
|
||||
if err := rLS.V1ResourceLimitsForEvent(map[string]interface{}{"Account": "1002", "Subject": "dan", "Destination": "1002"}, &rcvLmts); err != nil {
|
||||
t.Error(err)
|
||||
} else if len(eLimits) != len(rcvLmts) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eLimits, rcvLmts)
|
||||
|
||||
rls = ResourceLimits{rl2, rl}
|
||||
rls.Sort()
|
||||
|
||||
if rls[0].ID != "RL1" {
|
||||
t.Error("Sort failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRLsV1InitiateResourceUsage(t *testing.T) {
|
||||
attrRU := utils.AttrRLsResourceUsage{
|
||||
UsageID: "651a8db2-4f67-4cf8-b622-169e8a482e50",
|
||||
Event: map[string]interface{}{"Account": "1002", "Subject": "dan", "Destination": "1002"},
|
||||
Units: 1,
|
||||
}
|
||||
var reply string
|
||||
if err := rLS.V1AllocateResource(attrRU, &reply); err != nil {
|
||||
t.Error(err)
|
||||
} else if reply != "RL1" {
|
||||
t.Error("Received reply: ", reply)
|
||||
}
|
||||
resLimits, err := rLS.matchingResourceLimitsForEvent(attrRU.Event)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if len(resLimits) != 2 {
|
||||
t.Errorf("Received: %+v", resLimits)
|
||||
} else if resLimits[0].UsedUnits() != 1 {
|
||||
t.Errorf("RL1: %+v", resLimits[0])
|
||||
} else if _, hasKey := resLimits[0].Usage[attrRU.UsageID]; !hasKey {
|
||||
t.Errorf("RL1: %+v", resLimits[0])
|
||||
func TestRLsClearUsage(t *testing.T) {
|
||||
rls.ClearUsage(ru2.ID)
|
||||
for _, rl := range rls {
|
||||
if len(rl.Usage) > 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, len(rl.Usage))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRLsV1TerminateResourceUsage(t *testing.T) {
|
||||
attrRU := utils.AttrRLsResourceUsage{
|
||||
UsageID: "651a8db2-4f67-4cf8-b622-169e8a482e50",
|
||||
Event: map[string]interface{}{"Account": "1002", "Subject": "dan", "Destination": "1002"},
|
||||
Units: 1,
|
||||
}
|
||||
var reply string
|
||||
if err := rLS.V1ReleaseResource(attrRU, &reply); err != nil {
|
||||
t.Error(err)
|
||||
} else if reply != utils.OK {
|
||||
t.Error("Received reply: ", reply)
|
||||
}
|
||||
resLimits, err := rLS.matchingResourceLimitsForEvent(attrRU.Event)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if len(resLimits) != 2 {
|
||||
t.Errorf("Received: %+v", resLimits)
|
||||
} else if resLimits[0].UsedUnits() != 0 {
|
||||
t.Errorf("RL1: %+v", resLimits[0])
|
||||
} else if _, hasKey := resLimits[0].Usage[attrRU.UsageID]; hasKey {
|
||||
t.Errorf("RL1: %+v", resLimits[0])
|
||||
func TestRLsRecordUsages(t *testing.T) {
|
||||
if err := rls.RecordUsage(ru); err != nil {
|
||||
for _, rl := range rls {
|
||||
if _, found := rl.Usage[ru.ID]; found {
|
||||
t.Error("Fallback on error failed")
|
||||
}
|
||||
}
|
||||
t.Error(err.Error())
|
||||
} else {
|
||||
for _, rl := range rls {
|
||||
if _, found := rl.Usage[ru.ID]; !found {
|
||||
t.Error("ResourceUsage not found ")
|
||||
}
|
||||
if rl.TotalUsage != 2 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 2, rl.TotalUsage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRLsAllocateResource(t *testing.T) {
|
||||
rls.ClearUsage(ru.ID)
|
||||
rls.ClearUsage(ru2.ID)
|
||||
|
||||
rls[0].UsageTTL = time.Duration(20 * time.Second)
|
||||
rls[1].UsageTTL = time.Duration(20 * time.Second)
|
||||
ru.Time = time.Now()
|
||||
ru2.Time = time.Now()
|
||||
|
||||
if alcMessage, err := rls.AllocateResource(ru, false); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else {
|
||||
if alcMessage != "ALLOC" {
|
||||
t.Errorf("Wrong allocation message: %v", alcMessage)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := rls.AllocateResource(ru2, false); err != utils.ErrResourceUnavailable {
|
||||
t.Error("Did not receive " + utils.ErrResourceUnavailable.Error() + " error")
|
||||
}
|
||||
|
||||
rls[0].Limit = 2
|
||||
rls[1].Limit = 4
|
||||
|
||||
if alcMessage, err := rls.AllocateResource(ru, true); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else {
|
||||
if alcMessage != "RL2" {
|
||||
t.Errorf("Wrong allocation message: %v", alcMessage)
|
||||
}
|
||||
}
|
||||
|
||||
if alcMessage, err := rls.AllocateResource(ru2, false); err != nil {
|
||||
t.Error(err.Error())
|
||||
} else {
|
||||
if alcMessage != "RL2" {
|
||||
t.Errorf("Wrong allocation message: %v", alcMessage)
|
||||
}
|
||||
}
|
||||
|
||||
ru2.Units = 0
|
||||
if _, err := rls.AllocateResource(ru2, false); err == nil {
|
||||
t.Error("Duplicate ResourceUsage id should not be allowed")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user