diff --git a/apier/v1/accountprofiles_it_test.go b/apier/v1/accountprofiles_it_test.go index 15ca2617f..6fd54e98d 100644 --- a/apier/v1/accountprofiles_it_test.go +++ b/apier/v1/accountprofiles_it_test.go @@ -27,11 +27,10 @@ import ( "testing" "time" - "github.com/ericlagergren/decimal" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" + "github.com/ericlagergren/decimal" ) var ( @@ -131,46 +130,69 @@ func testAccountSGetAccountProfile(t *testing.T) { expected := &utils.AccountProfile{ Tenant: "cgrates.org", ID: "1001", - FilterIDs: []string{}, - Weight: 20, + FilterIDs: []string{"*string:~*req.Account:1001"}, Balances: map[string]*utils.Balance{ - "MonetaryBalance": &utils.Balance{ - ID: "MonetaryBalance", + "GenericBalance1": { + ID: "GenericBalance1", FilterIDs: []string{}, - Weight: 10, - Type: utils.MetaMonetary, - CostIncrements: []*utils.CostIncrement{ - &utils.CostIncrement{ - FilterIDs: []string{"fltr1", "fltr2"}, - Increment: &utils.Decimal{decimal.New(13, 1)}, - FixedFee: &utils.Decimal{decimal.New(23, 1)}, - RecurrentFee: &utils.Decimal{decimal.New(33, 1)}, - }, - }, - AttributeIDs: []string{"attr1", "attr2"}, + Weight: 20, + Blocker: false, + Type: "*abstract", + CostIncrements: []*utils.CostIncrement{{ + FilterIDs: []string{"*string:~*req.ToR:*voice"}, + Increment: &utils.Decimal{Big: decimal.New(1000000000, 0)}, + FixedFee: &utils.Decimal{Big: decimal.New(0, 0)}, + RecurrentFee: &utils.Decimal{Big: decimal.New(1, 2)}, + }, { + FilterIDs: []string{"*string:~*req.ToR:*data"}, + Increment: &utils.Decimal{Big: decimal.New(1024, 0)}, + FixedFee: &utils.Decimal{Big: decimal.New(0, 0)}, + RecurrentFee: &utils.Decimal{Big: decimal.New(1, 2)}, + }}, + AttributeIDs: []string{}, RateProfileIDs: []string{}, - UnitFactors: []*utils.UnitFactor{ - &utils.UnitFactor{ - FilterIDs: []string{"fltr1", "fltr2"}, - Factor: &utils.Decimal{decimal.New(100, 0)}, - }, - &utils.UnitFactor{ - FilterIDs: []string{"fltr3"}, - Factor: &utils.Decimal{decimal.New(200, 0)}, - }, - }, - Units: &utils.Decimal{decimal.New(14, 0)}, + UnitFactors: []*utils.UnitFactor{{ + FilterIDs: []string{"*string:~*req.ToR:*voice"}, + Factor: &utils.Decimal{Big: decimal.New(1000000000, 0)}, + }, { + FilterIDs: []string{"*string:~*req.ToR:*data"}, + Factor: &utils.Decimal{Big: decimal.New(1024000000000, 0)}, + }}, + Units: &utils.Decimal{Big: decimal.New(3600000000000, 0)}, }, - "VoiceBalance": &utils.Balance{ - ID: "VoiceBalance", + "MonetaryBalance1": { + ID: "MonetaryBalance1", + FilterIDs: []string{}, + Weight: 30, + Blocker: false, + Type: "*concrete", + CostIncrements: []*utils.CostIncrement{{ + FilterIDs: []string{"*string:~*req.ToR:*voice"}, + Increment: &utils.Decimal{Big: decimal.New(1000000000, 0)}, + FixedFee: &utils.Decimal{Big: decimal.New(0, 0)}, + RecurrentFee: &utils.Decimal{Big: decimal.New(1, 2)}, + }, { + FilterIDs: []string{"*string:~*req.ToR:*data"}, + Increment: &utils.Decimal{Big: decimal.New(1024, 0)}, + FixedFee: &utils.Decimal{Big: decimal.New(0, 0)}, + RecurrentFee: &utils.Decimal{Big: decimal.New(1, 2)}, + }}, + AttributeIDs: []string{}, + RateProfileIDs: []string{}, + UnitFactors: []*utils.UnitFactor{}, + Units: &utils.Decimal{Big: decimal.New(5, 0)}, + }, + "MonetaryBalance2": { + ID: "MonetaryBalance2", FilterIDs: []string{}, Weight: 10, - Type: utils.MetaVoice, + Blocker: false, + Type: "*concrete", CostIncrements: []*utils.CostIncrement{}, AttributeIDs: []string{}, RateProfileIDs: []string{}, UnitFactors: []*utils.UnitFactor{}, - Units: &utils.Decimal{decimal.New(3600000000000, 0)}, + Units: &utils.Decimal{Big: decimal.New(3, 0)}, }, }, ThresholdIDs: []string{utils.MetaNone}, @@ -207,13 +229,13 @@ func testAccountSSettAccountProfile(t *testing.T) { ID: "id_test", Weight: 10, Balances: map[string]*utils.APIBalance{ - "MonetaryBalance": &utils.APIBalance{ + "MonetaryBalance": { ID: "MonetaryBalance", FilterIDs: []string{}, Weight: 10, Type: utils.MetaMonetary, CostIncrements: []*utils.APICostIncrement{ - &utils.APICostIncrement{ + { FilterIDs: []string{"fltr1", "fltr2"}, Increment: utils.Float64Pointer(1.3), FixedFee: utils.Float64Pointer(2.3), @@ -222,18 +244,18 @@ func testAccountSSettAccountProfile(t *testing.T) { }, AttributeIDs: []string{"attr1", "attr2"}, UnitFactors: []*utils.APIUnitFactor{ - &utils.APIUnitFactor{ + { FilterIDs: []string{"fltr1", "fltr2"}, Factor: 100, }, - &utils.APIUnitFactor{ + { FilterIDs: []string{"fltr3"}, Factor: 200, }, }, Units: 14, }, - "VoiceBalance": &utils.APIBalance{ + "VoiceBalance": { ID: "VoiceBalance", FilterIDs: []string{}, Weight: 10, @@ -273,7 +295,7 @@ func testAccountSSettAccountProfile(t *testing.T) { } func testAccountSGetAccountProfileIDs(t *testing.T) { - expected := []string{"id_test", "1001"} + expected := []string{"id_test", "1001", "1002"} var result []string if err := accSRPC.Call(utils.APIerSv1GetAccountProfileIDs, utils.PaginatorWithTenant{}, &result); err != nil { t.Error(err) @@ -301,8 +323,8 @@ func testAccountSGetAccountProfileIDsCount(t *testing.T) { if err := accSRPC.Call(utils.APIerSv1GetAccountProfileIDsCount, &utils.TenantWithOpts{Tenant: "cgrates.org"}, &reply); err != nil { t.Error(err) - } else if reply != 2 { - t.Errorf("Expecting: 2, received: %+v", reply) + } else if reply != 3 { + t.Errorf("Expecting: 3, received: %+v", reply) } } diff --git a/apier/v1/resourcesv1_it_test.go b/apier/v1/resourcesv1_it_test.go index d7180adf6..a218c1ed2 100644 --- a/apier/v1/resourcesv1_it_test.go +++ b/apier/v1/resourcesv1_it_test.go @@ -68,6 +68,10 @@ var ( testV1RsSetResourceProfileWithOpts, testV1RsAuthorizeResourcesWithOpts, testV1RsStopEngine, + testV1RsStartEngine, + testV1RsRpcConn, + testV1RsCheckAuthorizeResourcesAfterRestart, + testV1RsStopEngine, } ) @@ -888,7 +892,7 @@ func testV1RsStopEngine(t *testing.T) { func testV1RsGetResourceProfileWithoutTenant(t *testing.T) { rlsConfig = &ResourceWithCache{ ResourceProfile: &engine.ResourceProfile{ - ID: rlsConfig.ID, + ID: "RES_ULTIMITED2", FilterIDs: []string{"*string:~*req.CustomField:UnlimitedEvent"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), @@ -946,7 +950,6 @@ func testV1RsSetResourceProfileWithOpts(t *testing.T) { UsageTTL: time.Duration(1) * time.Nanosecond, Limit: 10, Blocker: true, - Stored: true, Weight: 20, }, } @@ -991,4 +994,48 @@ func testV1RsAuthorizeResourcesWithOpts(t *testing.T) { } else if reply != "TEST_WITH_OPTS" { t.Error("Unexpected reply returned", reply) } + if err := rlsV1Rpc.Call(utils.ResourceSv1AllocateResources, + &argsRU, + &reply); err != nil { + t.Error(err) + } else if reply != "TEST_WITH_OPTS" { + t.Error("Unexpected reply returned", reply) + } +} + +func testV1RsCheckAuthorizeResourcesAfterRestart(t *testing.T) { + var rplyRes *engine.Resource + expRes := &engine.Resource{ + Tenant: "cgrates.org", + ID: "RES_ULTIMITED", + Usages: map[string]*engine.ResourceUsage{ + "651a8db2-4f67-4cf8-b622-169e8a482e51": { + Tenant: "cgrates.org", + ID: "651a8db2-4f67-4cf8-b622-169e8a482e51", + Units: 1, + }, + }, + } + if err := rlsV1Rpc.Call(utils.ResourceSv1GetResource, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "RES_ULTIMITED"}, + }, &rplyRes); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expRes, rplyRes) { + t.Errorf("Expecting: %+v, received: %+v", expRes, rplyRes) + } + + rplyRes = new(engine.Resource) + expRes = &engine.Resource{ + Tenant: "cgrates.org", + ID: "TEST_WITH_OPTS", + Usages: map[string]*engine.ResourceUsage{}, + } + if err := rlsV1Rpc.Call(utils.ResourceSv1GetResource, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "TEST_WITH_OPTS"}, + }, &rplyRes); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expRes, rplyRes) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expRes), utils.ToJSON(rplyRes)) + } + } diff --git a/apier/v1/stats_it_test.go b/apier/v1/stats_it_test.go index b618d4990..c215c8b08 100644 --- a/apier/v1/stats_it_test.go +++ b/apier/v1/stats_it_test.go @@ -93,6 +93,11 @@ var ( testV1STSProcessStatWithThreshold2, testV1STSSimulateAccountUpdate, testV1STSGetStatQueueWithoutExpired, + testV1STSGetStatQueueWithoutStored, + testV1STSStopEngine, + testV1STSStartEngine, + testV1STSRpcConn, + testV1STSCheckMetricsAfterRestart, testV1STSStopEngine, } ) @@ -1539,3 +1544,109 @@ func testV1STSGetStatQueueWithoutExpired(t *testing.T) { t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) } } + +func testV1STSGetStatQueueWithoutStored(t *testing.T) { + var result string + var reply *engine.StatQueueProfile + statConfig = &engine.StatQueueWithCache{ + StatQueueProfile: &engine.StatQueueProfile{ + Tenant: "cgrates.org", + ID: "Sq1NotStored", + FilterIDs: []string{"*string:~*req.StatQ:Sq1NotStored"}, + QueueLength: 10, + TTL: time.Second, + Metrics: []*engine.MetricWithFilters{{ + MetricID: utils.MetaTCD, + }}, + Blocker: true, + Weight: 200, + MinItems: 1, + }, + } + if err := stsV1Rpc.Call(utils.APIerSv1SetStatQueueProfile, statConfig, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + if err := stsV1Rpc.Call(utils.APIerSv1GetStatQueueProfile, + &utils.TenantID{Tenant: "cgrates.org", ID: "Sq1NotStored"}, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(statConfig.StatQueueProfile, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(statConfig.StatQueueProfile), utils.ToJSON(reply)) + } + + var metrics map[string]string + expectedMetrics := map[string]string{ + utils.MetaTCD: "10s", + } + //process event + var reply2 []string + expected := []string{"Sq1NotStored"} + args := engine.StatsArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "Sq1NotStored", + Event: map[string]interface{}{ + "StatQ": "Sq1NotStored", + utils.Usage: 10 * time.Second, + }, + }, + } + if err := stsV1Rpc.Call(utils.StatSv1ProcessEvent, &args, &reply2); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply2, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply2) + } + //verify metrics after first process + if err := stsV1Rpc.Call(utils.StatSv1GetQueueStringMetrics, + &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "Sq1NotStored"}}, &metrics); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedMetrics, metrics) { + t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) + } + if err := stsV1Rpc.Call(utils.APIerSv1SetStatQueueProfile, statConfig, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + if err := stsV1Rpc.Call(utils.StatSv1ProcessEvent, &args, &reply2); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply2, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply2) + } + //verify metrics after first process + if err := stsV1Rpc.Call(utils.StatSv1GetQueueStringMetrics, + &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "Sq1NotStored"}}, &metrics); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedMetrics, metrics) { + t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) + } +} + +func testV1STSCheckMetricsAfterRestart(t *testing.T) { + var metrics map[string]string + + expectedMetrics := map[string]string{ + utils.MetaSum + utils.HashtagSep + "~*asm.BalanceSummaries.HolidayBalance.Value": "3", + } + if err := stsV1Rpc.Call(utils.StatSv1GetQueueStringMetrics, + &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "StatForAccountUpdate"}}, &metrics); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedMetrics, metrics) { + t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) + } + expectedMetrics = map[string]string{ + utils.MetaTCD: utils.NotAvailable, + } + metrics = map[string]string{} + if err := stsV1Rpc.Call(utils.StatSv1GetQueueStringMetrics, + &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "Sq1NotStored"}}, &metrics); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedMetrics, metrics) { + t.Errorf("expecting: %+v, received reply: %s", expectedMetrics, metrics) + } +} diff --git a/engine/libattributes_test.go b/engine/libattributes_test.go index d4c447e63..a1644c304 100644 --- a/engine/libattributes_test.go +++ b/engine/libattributes_test.go @@ -148,11 +148,12 @@ func TestNewAttributeFromInlineWithMultipleRuns(t *testing.T) { Tenant: config.CgrConfig().GeneralCfg().DefaultTenant, ID: attrID, Contexts: []string{utils.MetaAny}, - Attributes: []*Attribute{{ - Path: utils.MetaReq + utils.NestingSep + "RequestType", - Type: utils.MetaConstant, - Value: config.NewRSRParsersMustCompile("*rated", utils.InfieldSep), - }, + Attributes: []*Attribute{ + { + Path: utils.MetaReq + utils.NestingSep + "RequestType", + Type: utils.MetaConstant, + Value: config.NewRSRParsersMustCompile("*rated", utils.InfieldSep), + }, { Path: utils.MetaReq + utils.NestingSep + "Category", Type: utils.MetaConstant, diff --git a/engine/libcdre.go b/engine/libcdre.go index 247023fd1..013b9b882 100644 --- a/engine/libcdre.go +++ b/engine/libcdre.go @@ -115,7 +115,7 @@ type ExportEvents struct { // FileName returns the file name it should use for saving the failed events func (expEv *ExportEvents) FileName() string { - return expEv.module + utils.HandlerArgSep + utils.UUIDSha1Prefix() + utils.GOBSuffix + return expEv.module + utils.PipeSep + utils.UUIDSha1Prefix() + utils.GOBSuffix } // SetModule sets the module for this event diff --git a/utils/consts.go b/utils/consts.go index 2f025a662..b41e80554 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -460,7 +460,6 @@ const ( MetaRaw = "*raw" CreatedAt = "CreatedAt" UpdatedAt = "UpdatedAt" - HandlerArgSep = "|" NodeID = "NodeID" ActiveGoroutines = "ActiveGoroutines" MemoryUsage = "MemoryUsage"