// Called by rate/re-rate API func (self *CdrServer) RateCdrs(cgrIds, runIds, tors, cdrHosts, cdrSources, reqTypes, directions, tenants, categories, accounts, subjects, destPrefixes, ratedAccounts, ratedSubjects []string, orderIdStart, orderIdEnd int64, timeStart, timeEnd time.Time, rerateErrors, rerateRated, sendToStats bool) error { var costStart, costEnd *float64 if rerateErrors { costStart = utils.Float64Pointer(-1.0) if !rerateRated { costEnd = utils.Float64Pointer(0.0) } } else if rerateRated { costStart = utils.Float64Pointer(0.0) } cdrs, _, err := self.cdrDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: cgrIds, RunIds: runIds, Tors: tors, CdrHosts: cdrHosts, CdrSources: cdrSources, ReqTypes: reqTypes, Directions: directions, Tenants: tenants, Categories: categories, Accounts: accounts, Subjects: subjects, DestPrefixes: destPrefixes, RatedAccounts: ratedAccounts, RatedSubjects: ratedSubjects, OrderIdStart: orderIdStart, OrderIdEnd: orderIdEnd, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, MinCost: costStart, MaxCost: costEnd}) if err != nil { return err } for _, cdr := range cdrs { if err := self.processCdr(cdr); err != nil { Logger.Err(fmt.Sprintf("<CDRS> Processing CDR %+v, got error: %s", cdr, err.Error())) } } return nil }
func TestApierV2itSetAccountActionTriggers(t *testing.T) { attrs := AttrSetAccountActionTriggers{ Tenant: "cgrates.org", Account: "dan", GroupID: utils.StringPointer("MONITOR_MAX_BALANCE"), ThresholdType: utils.StringPointer(utils.TRIGGER_MAX_BALANCE), ThresholdValue: utils.Float64Pointer(50), BalanceType: utils.StringPointer(utils.MONETARY), ActionsID: utils.StringPointer("DISABLE_ACCOUNT"), } var reply string if err := apierRPC.Call("ApierV2.SetAccountActionTriggers", attrs, &reply); err != nil { t.Error(err) } var ats engine.ActionTriggers if err := apierRPC.Call("ApierV2.GetAccountActionTriggers", v1.AttrAcntAction{Tenant: "cgrates.org", Account: "dan"}, &ats); err != nil { t.Error(err) } else if len(ats) != 1 || ats[0].ID != *attrs.GroupID || ats[0].ThresholdValue != 50.0 { t.Errorf("Received: %+v", ats) } attrs.ThresholdValue = utils.Float64Pointer(55) // Change the threshold if err := apierRPC.Call("ApierV2.SetAccountActionTriggers", attrs, &reply); err != nil { t.Error(err) } if err := apierRPC.Call("ApierV2.GetAccountActionTriggers", v1.AttrAcntAction{Tenant: "cgrates.org", Account: "dan"}, &ats); err != nil { t.Error(err) } else if len(ats) != 1 || ats[0].ID != *attrs.GroupID || ats[0].ThresholdValue != 55.0 { t.Errorf("Received: %+v", ats) } }
func testOnStorITCacheActions(t *testing.T) { acts := Actions{ &Action{ Id: "MINI", ActionType: TOPUP_RESET, ExpirationString: UNLIMITED, Weight: 10, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MONETARY), Uuid: utils.StringPointer(utils.GenUUID()), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Value: &utils.ValueFormula{Static: 10, Params: make(map[string]interface{})}, Weight: utils.Float64Pointer(10), Disabled: utils.BoolPointer(false), Timings: make([]*RITiming, 0), Blocker: utils.BoolPointer(false), }, }, &Action{ Id: "MINI", ActionType: TOPUP, ExpirationString: UNLIMITED, Weight: 10, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.VOICE), Uuid: utils.StringPointer(utils.GenUUID()), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Value: &utils.ValueFormula{Static: 100, Params: make(map[string]interface{})}, Weight: utils.Float64Pointer(10), RatingSubject: utils.StringPointer("test"), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Disabled: utils.BoolPointer(false), Timings: make([]*RITiming, 0), Blocker: utils.BoolPointer(false), }, }, } if err := onStor.SetActions(acts[0].Id, acts, utils.NonTransactional); err != nil { t.Error(err) } if _, hasIt := cache.Get(utils.ACTION_PREFIX + acts[0].Id); hasIt { t.Error("Already in cache") } if err := onStor.CacheDataFromDB(utils.ACTION_PREFIX, []string{acts[0].Id}, false); err != nil { t.Error(err) } if itm, hasIt := cache.Get(utils.ACTION_PREFIX + acts[0].Id); !hasIt { t.Error("Did not cache") } else if rcv := itm.(Actions); !reflect.DeepEqual(acts, rcv) { t.Errorf("Expecting: %+v, received: %+v", acts, rcv) } }
func TestV2CdrsMongoGetCdrs(t *testing.T) { if !*testLocal { return } var reply []*engine.ExternalCdr req := utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}} if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 4 { for _, cdr := range reply { t.Logf("CDR: %s %s %s", cdr.CgrId, cdr.CdrSource, cdr.MediationRunId) } t.Error("Unexpected number of CDRs returned: ", len(reply)) } // CDRs with errors req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)} if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 2 { t.Error("Unexpected number of CDRs returned: ", reply) } // CDRs Rated req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, MinCost: utils.Float64Pointer(-1.0)} if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 4 { for _, cdr := range reply { t.Logf("CDR: %s %s %s %f", cdr.CgrId, cdr.CdrSource, cdr.MediationRunId, cdr.Cost) } t.Error("Unexpected number of CDRs returned: ", reply) } // CDRs non rated OR SkipRated req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, MaxCost: utils.Float64Pointer(-1.0)} if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 0 { for _, cdr := range reply { t.Logf("CDR: %s %s %s %f", cdr.CgrId, cdr.CdrSource, cdr.MediationRunId, cdr.Cost) } t.Error("Unexpected number of CDRs returned: ", reply) } // Skip Errors req = utils.RpcCdrsFilter{NotCdrSources: []string{"CDRS"}, MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)} if err := cdrsMongoRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 2 { for _, cdr := range reply { t.Logf("CDR: %s %s %s %f", cdr.CgrId, cdr.CdrSource, cdr.MediationRunId, cdr.Cost) } t.Error("Unexpected number of CDRs returned: ", reply) } }
func TestBalanceMatchFilterDiffId(t *testing.T) { mb1 := &Balance{ID: "T1", Weight: 1, precision: 1, RatingSubject: "1", DestinationIDs: utils.StringMap{}} mb2 := &BalanceFilter{ID: utils.StringPointer("T2"), Weight: utils.Float64Pointer(1), RatingSubject: utils.StringPointer("1"), DestinationIDs: nil} if mb1.MatchFilter(mb2, false) { t.Errorf("Match filter failure: %+v != %+v", mb1, mb2) } }
func TestBalanceMatchFilter(t *testing.T) { mb1 := &Balance{Weight: 1, precision: 1, RatingSubject: "1", DestinationIDs: utils.StringMap{}} mb2 := &BalanceFilter{Weight: utils.Float64Pointer(1), RatingSubject: nil, DestinationIDs: nil} if !mb1.MatchFilter(mb2, false) { t.Errorf("Match filter failure: %+v == %+v", mb1, mb2) } }
func TestBalanceMatchFilterId(t *testing.T) { mb1 := &Balance{ID: "T1", Weight: 2, precision: 2, RatingSubject: "2", DestinationIDs: utils.NewStringMap("NAT")} mb2 := &BalanceFilter{ID: utils.StringPointer("T1"), Weight: utils.Float64Pointer(1), RatingSubject: utils.StringPointer("1"), DestinationIDs: nil} if !mb1.MatchFilter(mb2, false) { t.Errorf("Match filter failure: %+v == %+v", mb1, mb2) } }
func TestNewCgrJsonCfgFromFile(t *testing.T) { cgrJsonCfg, err := NewCgrJsonCfgFromFile("cfg_data.json") if err != nil { t.Error(err) } eCfg := &GeneralJsonCfg{Default_reqtype: utils.StringPointer(utils.META_PSEUDOPREPAID)} if gCfg, err := cgrJsonCfg.GeneralJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfg, gCfg) { t.Error("Received: ", gCfg) } cdrFields := []*CdrFieldJsonCfg{ &CdrFieldJsonCfg{Cdr_field_id: utils.StringPointer(utils.TOR), Value: utils.StringPointer("~7:s/^(voice|data|sms|generic)$/*$1/")}, &CdrFieldJsonCfg{Cdr_field_id: utils.StringPointer(utils.ANSWER_TIME), Value: utils.StringPointer("1")}, &CdrFieldJsonCfg{Cdr_field_id: utils.StringPointer(utils.USAGE), Value: utils.StringPointer(`~9:s/^(\d+)$/${1}s/`)}, } eCfgCdrc := map[string]*CdrcJsonCfg{ "CDRC-CSV1": &CdrcJsonCfg{ Enabled: utils.BoolPointer(true), Cdr_in_dir: utils.StringPointer("/tmp/cgrates/cdrc1/in"), Cdr_out_dir: utils.StringPointer("/tmp/cgrates/cdrc1/out"), Cdr_source_id: utils.StringPointer("csv1"), }, "CDRC-CSV2": &CdrcJsonCfg{ Enabled: utils.BoolPointer(true), Data_usage_multiply_factor: utils.Float64Pointer(0.000976563), Run_delay: utils.IntPointer(1), Cdr_in_dir: utils.StringPointer("/tmp/cgrates/cdrc2/in"), Cdr_out_dir: utils.StringPointer("/tmp/cgrates/cdrc2/out"), Cdr_source_id: utils.StringPointer("csv2"), Content_fields: &cdrFields, }, } if cfg, err := cgrJsonCfg.CdrcJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfgCdrc, cfg) { t.Error("Received: ", cfg["CDRC-CSV2"]) } eCfgSmFs := &SmFsJsonCfg{ Enabled: utils.BoolPointer(true), Connections: &[]*FsConnJsonCfg{ &FsConnJsonCfg{ Server: utils.StringPointer("1.2.3.4:8021"), Password: utils.StringPointer("ClueCon"), Reconnects: utils.IntPointer(5), }, &FsConnJsonCfg{ Server: utils.StringPointer("2.3.4.5:8021"), Password: utils.StringPointer("ClueCon"), Reconnects: utils.IntPointer(5), }, }, } if smFsCfg, err := cgrJsonCfg.SmFsJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfgSmFs, smFsCfg) { t.Error("Received: ", smFsCfg) } }
// Deprecated in rc8, replaced by AddAccountActionTriggers func (self *ApierV1) AddTriggeredAction(attr AttrAddActionTrigger, reply *string) error { if missing := utils.MissingStructFields(&attr, []string{"Tenant", "Account"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } at := &engine.ActionTrigger{ ID: attr.ActionTriggersId, ThresholdType: attr.ThresholdType, ThresholdValue: attr.ThresholdValue, Balance: new(engine.BalanceFilter), Weight: attr.Weight, ActionsID: attr.ActionsId, } if attr.BalanceId != "" { at.Balance.ID = utils.StringPointer(attr.BalanceId) } if attr.BalanceType != "" { at.Balance.Type = utils.StringPointer(attr.BalanceType) } if attr.BalanceDirection != "" { at.Balance.Directions = &utils.StringMap{attr.BalanceDirection: true} } if attr.BalanceDestinationIds != "" { dstIDsMp := utils.StringMapFromSlice(strings.Split(attr.BalanceDestinationIds, utils.INFIELD_SEP)) at.Balance.DestinationIDs = &dstIDsMp } if attr.BalanceRatingSubject != "" { at.Balance.RatingSubject = utils.StringPointer(attr.BalanceRatingSubject) } if attr.BalanceWeight != 0.0 { at.Balance.Weight = utils.Float64Pointer(attr.BalanceWeight) } if balExpiryTime, err := utils.ParseTimeDetectLayout(attr.BalanceExpiryTime, self.Config.DefaultTimezone); err != nil { return utils.NewErrServerError(err) } else { at.Balance.ExpirationDate = &balExpiryTime } if attr.BalanceSharedGroup != "" { at.Balance.SharedGroups = &utils.StringMap{attr.BalanceSharedGroup: true} } acntID := utils.AccountKey(attr.Tenant, attr.Account) _, err := engine.Guardian.Guard(func() (interface{}, error) { acnt, err := self.AccountDb.GetAccount(acntID) if err != nil { return 0, err } acnt.ActionTriggers = append(acnt.ActionTriggers, at) if err = self.AccountDb.SetAccount(acnt); err != nil { return 0, err } return 0, nil }, 0, acntID) if err != nil { return err } *reply = OK return nil }
// Called by rate/re-rate API func (self *CdrServer) RateCdrs(cgrIds, runIds, tors, cdrHosts, cdrSources, reqTypes, directions, tenants, categories, accounts, subjects, destPrefixes, ratedAccounts, ratedSubjects []string, orderIdStart, orderIdEnd int64, timeStart, timeEnd time.Time, rerateErrors, rerateRated, sendToStats bool) error { var costStart, costEnd *float64 if rerateErrors { costStart = utils.Float64Pointer(-1.0) if !rerateRated { costEnd = utils.Float64Pointer(0.0) } } else if rerateRated { costStart = utils.Float64Pointer(0.0) } cdrs, _, err := self.cdrDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: cgrIds, RunIds: runIds, Tors: tors, CdrHosts: cdrHosts, CdrSources: cdrSources, ReqTypes: reqTypes, Directions: directions, Tenants: tenants, Categories: categories, Accounts: accounts, Subjects: subjects, DestPrefixes: destPrefixes, RatedAccounts: ratedAccounts, RatedSubjects: ratedSubjects, OrderIdStart: orderIdStart, OrderIdEnd: orderIdEnd, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, MinCost: costStart, MaxCost: costEnd}) if err != nil { return err } for _, cdr := range cdrs { if cdr.MediationRunId == "" { // raw CDRs which were not calculated before cdr.MediationRunId = utils.META_DEFAULT } // replace aliases for cases they were loaded after CDR received if err := LoadAlias(&AttrMatchingAlias{ Destination: cdr.Destination, Direction: cdr.Direction, Tenant: cdr.Tenant, Category: cdr.Category, Account: cdr.Account, Subject: cdr.Subject, Context: utils.ALIAS_CONTEXT_RATING, }, cdr, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound { return err } // replace user profile fields if err := LoadUserProfile(cdr, utils.EXTRA_FIELDS); err != nil { return err } if err := self.rateStoreStatsReplicate(cdr); err != nil { utils.Logger.Err(fmt.Sprintf("<CDRS> Processing CDR %+v, got error: %s", cdr, err.Error())) } } return nil }
func TestDfCdrcJsonCfg(t *testing.T) { eFields := []*CdrFieldJsonCfg{} cdrFields := []*CdrFieldJsonCfg{ &CdrFieldJsonCfg{Tag: utils.StringPointer("tor"), Cdr_field_id: utils.StringPointer(utils.TOR), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("2"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("accid"), Cdr_field_id: utils.StringPointer(utils.ACCID), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("3"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("reqtype"), Cdr_field_id: utils.StringPointer(utils.REQTYPE), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("4"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("direction"), Cdr_field_id: utils.StringPointer(utils.DIRECTION), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("5"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("tenant"), Cdr_field_id: utils.StringPointer(utils.TENANT), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("6"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("category"), Cdr_field_id: utils.StringPointer(utils.CATEGORY), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("7"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("account"), Cdr_field_id: utils.StringPointer(utils.ACCOUNT), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("8"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("subject"), Cdr_field_id: utils.StringPointer(utils.SUBJECT), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("9"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("destination"), Cdr_field_id: utils.StringPointer(utils.DESTINATION), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("10"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("setup_time"), Cdr_field_id: utils.StringPointer(utils.SETUP_TIME), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("11"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("answer_time"), Cdr_field_id: utils.StringPointer(utils.ANSWER_TIME), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("12"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("usage"), Cdr_field_id: utils.StringPointer(utils.USAGE), Type: utils.StringPointer(utils.CDRFIELD), Value: utils.StringPointer("13"), Mandatory: utils.BoolPointer(true)}, } eCfg := map[string]*CdrcJsonCfg{ "*default": &CdrcJsonCfg{ Enabled: utils.BoolPointer(false), Dry_run: utils.BoolPointer(false), Cdrs: utils.StringPointer("internal"), Cdr_format: utils.StringPointer("csv"), Field_separator: utils.StringPointer(","), Timezone: utils.StringPointer(""), Run_delay: utils.IntPointer(0), Max_open_files: utils.IntPointer(1024), Data_usage_multiply_factor: utils.Float64Pointer(1024.0), Cdr_in_dir: utils.StringPointer("/var/log/cgrates/cdrc/in"), Cdr_out_dir: utils.StringPointer("/var/log/cgrates/cdrc/out"), Failed_calls_prefix: utils.StringPointer("missed_calls"), Cdr_source_id: utils.StringPointer("freeswitch_csv"), Cdr_filter: utils.StringPointer(""), Continue_on_success: utils.BoolPointer(false), Partial_record_cache: utils.StringPointer("10s"), Header_fields: &eFields, Content_fields: &cdrFields, Trailer_fields: &eFields, }, } if cfg, err := dfCgrJsonCfg.CdrcJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfg, cfg) { t.Error("Received: ", cfg["*default"]) } }
func TestApierV2itAddBalance(t *testing.T) { attrs := &utils.AttrSetBalance{ Tenant: "cgrates.org", Account: "dan", BalanceType: utils.MONETARY, BalanceID: utils.StringPointer(utils.META_DEFAULT), Value: utils.Float64Pointer(5.0), Weight: utils.Float64Pointer(10.0), } var reply string if err := apierRPC.Call("ApierV2.SetBalance", attrs, &reply); err != nil { t.Fatal(err) } var acnt engine.Account if err := apierRPC.Call("ApierV2.GetAccount", &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan"}, &acnt); err != nil { t.Error(err) } else if acnt.BalanceMap[utils.MONETARY][0].Value != 5.0 { t.Errorf("Unexpected balance received: %+v", acnt.BalanceMap[utils.MONETARY][0]) } }
func TestApierV2itFraudMitigation(t *testing.T) { if !*testIT { return } attrs := &utils.AttrSetBalance{ Tenant: "cgrates.org", Account: "dan", BalanceType: utils.MONETARY, BalanceID: utils.StringPointer(utils.META_DEFAULT), Value: utils.Float64Pointer(60.0), Weight: utils.Float64Pointer(10.0), } var reply string if err := apierRPC.Call("ApierV2.SetBalance", attrs, &reply); err != nil { t.Fatal(err) } var acnt engine.Account if err := apierRPC.Call("ApierV2.GetAccount", &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan"}, &acnt); err != nil { t.Error(err) } else if len(acnt.BalanceMap) != 1 || acnt.BalanceMap[utils.MONETARY][0].Value != 60.0 { t.Errorf("Unexpected balance received: %+v", acnt.BalanceMap[utils.MONETARY][0]) } else if !acnt.Disabled { t.Fatalf("Received account: %+v", acnt) } attrSetAcnt := AttrSetAccount{ Tenant: "cgrates.org", Account: "dan", Disabled: utils.BoolPointer(false), } if err := apierRPC.Call("ApierV2.SetAccount", attrSetAcnt, &reply); err != nil { t.Fatal(err) } if err := apierRPC.Call("ApierV2.GetAccount", &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "dan"}, &acnt); err != nil { t.Error(err) } else if len(acnt.BalanceMap) != 1 || acnt.BalanceMap[utils.MONETARY][0].Value != 60.0 { t.Errorf("Unexpected balance received: %+v", acnt.BalanceMap[utils.MONETARY][0]) } else if acnt.Disabled { t.Fatalf("Received account: %+v", acnt) } }
func TestV2CDRsPSQLGetCdrs(t *testing.T) { if !*testLocal { return } var reply []*engine.ExternalCDR req := utils.RPCCDRsFilter{} if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 4 { // 1 injected, 1 rated, 1 *raw and it's pair in *default run t.Error("Unexpected number of CDRs returned: ", len(reply)) } // CDRs with rating errors req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)} if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", reply) } // CDRs Rated req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}} if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 2 { t.Error("Unexpected number of CDRs returned: ", reply) } // Raw CDRs req = utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}} if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 2 { t.Error("Unexpected number of CDRs returned: ", reply) } // Skip Errors req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)} if err := cdrsPsqlRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", reply) } }
func TestBalanceMatchActionTriggerWeight(t *testing.T) { at := &ActionTrigger{Balance: &BalanceFilter{Weight: utils.Float64Pointer(1)}} b := &Balance{Weight: 1} if !b.MatchActionTrigger(at) { t.Errorf("Error matching action trigger: %+v %+v", b, at) } b.Weight = 2 if b.MatchActionTrigger(at) { t.Errorf("Error matching action trigger: %+v %+v", b, at) } b.Weight = 0 if b.MatchActionTrigger(at) { t.Errorf("Error matching action trigger: %+v %+v", b, at) } b.Weight = 1 at.Balance.Weight = nil if !b.MatchActionTrigger(at) { t.Errorf("Error matching action trigger: %+v %+v", b, at) } }
func TestV2CdrsMysqlGetCdrs(t *testing.T) { if !*testLocal { return } var reply []*engine.ExternalCdr req := utils.RpcCdrsFilter{} if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 4 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } // CDRs with errors req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(-1.0), MaxCost: utils.Float64Pointer(0.0)} if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 2 { t.Error("Unexpected number of CDRs returned: ", reply) } // CDRs Rated req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(-1.0)} if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 3 { t.Error("Unexpected number of CDRs returned: ", reply) } // CDRs non rated OR SkipRated req = utils.RpcCdrsFilter{MaxCost: utils.Float64Pointer(-1.0)} if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", reply) } // Skip Errors req = utils.RpcCdrsFilter{MinCost: utils.Float64Pointer(0.0), MaxCost: utils.Float64Pointer(-1.0)} if err := cdrsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 2 { t.Error("Unexpected number of CDRs returned: ", reply) } }
func (mig MigratorRC8) migrateAccountsInt() error { keys, err := mig.db.Cmd("KEYS", utils.ACCOUNT_PREFIX+"*").List() if err != nil { return err } newAccounts := make([]*engine.Account, 0) var migratedKeys []string // get existing accounts for _, key := range keys { log.Printf("Migrating account: %s...", key) values, err := mig.db.Cmd("GET", key).Bytes() if err != nil { continue } var oldAcc Account1 if err = mig.ms.Unmarshal(values, &oldAcc); err != nil { return err } // transfer data into new structurse newAcc := &engine.Account{ ID: oldAcc.Id, BalanceMap: make(map[string]engine.Balances, len(oldAcc.BalanceMap)), UnitCounters: make(engine.UnitCounters), ActionTriggers: make(engine.ActionTriggers, len(oldAcc.ActionTriggers)), AllowNegative: oldAcc.AllowNegative, Disabled: oldAcc.Disabled, } // balances balanceErr := false for key, oldBalChain := range oldAcc.BalanceMap { newAcc.BalanceMap[key] = make(engine.Balances, len(oldBalChain)) for index, oldBal := range oldBalChain { newAcc.BalanceMap[key][index] = &engine.Balance{ Uuid: oldBal.Uuid, ID: oldBal.Id, Value: oldBal.Value, Directions: oldBal.Directions, ExpirationDate: oldBal.ExpirationDate, Weight: oldBal.Weight, DestinationIDs: oldBal.DestinationIds, RatingSubject: oldBal.RatingSubject, Categories: oldBal.Categories, SharedGroups: oldBal.SharedGroups, Timings: oldBal.Timings, TimingIDs: oldBal.TimingIDs, Disabled: oldBal.Disabled, Factor: oldBal.Factor, Blocker: oldBal.Blocker, } } } if balanceErr { continue } // unit counters for _, oldUc := range oldAcc.UnitCounters { newUc := &engine.UnitCounter{ Counters: make(engine.CounterFilters, len(oldUc.Balances)), } for index, oldUcBal := range oldUc.Balances { b := &engine.Balance{ Uuid: oldUcBal.Uuid, ID: oldUcBal.Id, Value: oldUcBal.Value, Directions: oldUcBal.Directions, ExpirationDate: oldUcBal.ExpirationDate, Weight: oldUcBal.Weight, DestinationIDs: oldUcBal.DestinationIds, RatingSubject: oldUcBal.RatingSubject, Categories: oldUcBal.Categories, SharedGroups: oldUcBal.SharedGroups, Timings: oldUcBal.Timings, TimingIDs: oldUcBal.TimingIDs, Disabled: oldUcBal.Disabled, Factor: oldUcBal.Factor, Blocker: oldUcBal.Blocker, } bf := &engine.BalanceFilter{} bf.LoadFromBalance(b) cf := &engine.CounterFilter{ Value: oldUcBal.Value, Filter: bf, } newUc.Counters[index] = cf } newAcc.UnitCounters[oldUc.BalanceType] = append(newAcc.UnitCounters[oldUc.BalanceType], newUc) } // action triggers for index, oldAtr := range oldAcc.ActionTriggers { at := &engine.ActionTrigger{ ID: oldAtr.ID, UniqueID: oldAtr.UniqueID, ThresholdType: oldAtr.ThresholdType, ThresholdValue: oldAtr.ThresholdValue, Recurrent: oldAtr.Recurrent, MinSleep: oldAtr.MinSleep, Weight: oldAtr.Weight, ActionsID: oldAtr.ActionsId, MinQueuedItems: oldAtr.MinQueuedItems, Executed: oldAtr.Executed, } bf := &engine.BalanceFilter{} if oldAtr.BalanceId != "" { bf.ID = utils.StringPointer(oldAtr.BalanceId) } if oldAtr.BalanceType != "" { bf.Type = utils.StringPointer(oldAtr.BalanceType) } if oldAtr.BalanceRatingSubject != "" { bf.RatingSubject = utils.StringPointer(oldAtr.BalanceRatingSubject) } if !oldAtr.BalanceDirections.IsEmpty() { bf.Directions = utils.StringMapPointer(oldAtr.BalanceDirections) } if !oldAtr.BalanceDestinationIds.IsEmpty() { bf.DestinationIDs = utils.StringMapPointer(oldAtr.BalanceDestinationIds) } if !oldAtr.BalanceTimingTags.IsEmpty() { bf.TimingIDs = utils.StringMapPointer(oldAtr.BalanceTimingTags) } if !oldAtr.BalanceCategories.IsEmpty() { bf.Categories = utils.StringMapPointer(oldAtr.BalanceCategories) } if !oldAtr.BalanceSharedGroups.IsEmpty() { bf.SharedGroups = utils.StringMapPointer(oldAtr.BalanceSharedGroups) } if oldAtr.BalanceWeight != 0 { bf.Weight = utils.Float64Pointer(oldAtr.BalanceWeight) } if oldAtr.BalanceDisabled != false { bf.Disabled = utils.BoolPointer(oldAtr.BalanceDisabled) } if !oldAtr.BalanceExpirationDate.IsZero() { bf.ExpirationDate = utils.TimePointer(oldAtr.BalanceExpirationDate) } at.Balance = bf newAcc.ActionTriggers[index] = at } newAcc.InitCounters() newAccounts = append(newAccounts, newAcc) migratedKeys = append(migratedKeys, key) } // write data back for _, newAcc := range newAccounts { result, err := mig.ms.Marshal(newAcc) if err != nil { return err } if err := mig.db.Cmd("SET", utils.ACCOUNT_PREFIX+newAcc.ID, result).Err; err != nil { return err } } notMigrated := len(keys) - len(migratedKeys) if notMigrated > 0 { log.Printf("WARNING: there are %d accounts that failed migration!", notMigrated) } return err }
func TestLoadActions(t *testing.T) { if len(csvr.actions) != 15 { t.Error("Failed to load actions: ", len(csvr.actions)) } as1 := csvr.actions["MINI"] expected := []*Action{ &Action{ Id: "MINI", ActionType: TOPUP_RESET, ExpirationString: UNLIMITED, ExtraParameters: "", Weight: 10, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MONETARY), Uuid: as1[0].Balance.Uuid, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Value: &utils.ValueFormula{Static: 10}, Weight: utils.Float64Pointer(10), DestinationIDs: nil, TimingIDs: nil, SharedGroups: nil, Categories: nil, Disabled: utils.BoolPointer(false), Blocker: utils.BoolPointer(false), }, }, &Action{ Id: "MINI", ActionType: TOPUP, ExpirationString: UNLIMITED, ExtraParameters: "", Weight: 10, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.VOICE), Uuid: as1[1].Balance.Uuid, Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Value: &utils.ValueFormula{Static: 100}, Weight: utils.Float64Pointer(10), RatingSubject: utils.StringPointer("test"), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), TimingIDs: nil, SharedGroups: nil, Categories: nil, Disabled: utils.BoolPointer(false), Blocker: utils.BoolPointer(false), }, }, } if !reflect.DeepEqual(as1, expected) { t.Errorf("Error loading action1: %s", utils.ToIJSON(as1)) } as2 := csvr.actions["SHARED"] expected = []*Action{ &Action{ Id: "SHARED", ActionType: TOPUP, ExpirationString: UNLIMITED, Weight: 10, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), DestinationIDs: nil, Uuid: as2[0].Balance.Uuid, Value: &utils.ValueFormula{Static: 100}, Weight: utils.Float64Pointer(10), SharedGroups: utils.StringMapPointer(utils.NewStringMap("SG1")), TimingIDs: nil, Categories: nil, Disabled: utils.BoolPointer(false), Blocker: utils.BoolPointer(false), }, }, } if !reflect.DeepEqual(as2, expected) { t.Errorf("Error loading action: %s", utils.ToIJSON(as2)) } as3 := csvr.actions["DEFEE"] expected = []*Action{ &Action{ Id: "DEFEE", ActionType: CDRLOG, ExtraParameters: `{"Category":"^ddi","MediationRunId":"^did_run"}`, Weight: 10, Balance: &BalanceFilter{ Uuid: as3[0].Balance.Uuid, Directions: nil, DestinationIDs: nil, TimingIDs: nil, Categories: nil, SharedGroups: nil, Blocker: utils.BoolPointer(false), Disabled: utils.BoolPointer(false), }, }, } if !reflect.DeepEqual(as3, expected) { t.Errorf("Error loading action: %+v", as3[0].Balance) } }
func testGetCDRs(cfg *config.CGRConfig) error { if err := InitStorDb(cfg); err != nil { return err } cdrStorage, err := ConfigureCdrStorage(cfg.StorDBType, cfg.StorDBHost, cfg.StorDBPort, cfg.StorDBName, cfg.StorDBUser, cfg.StorDBPass, cfg.StorDBMaxOpenConns, cfg.StorDBMaxIdleConns, cfg.StorDBCDRSIndexes) if err != nil { return err } // All CDRs, no filter if CDRs, _, err := cdrStorage.GetCDRs(new(utils.CDRsFilter), false); err != nil { return err } else if len(CDRs) != 0 { return fmt.Errorf("Unexpected number of CDRs returned: ", CDRs) } cdrs := []*CDR{ &CDR{ CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), RunID: utils.MetaRaw, OriginHost: "127.0.0.1", Source: "testGetCDRs", OriginID: "testevent1", ToR: utils.VOICE, RequestType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC), PDD: time.Duration(20) * time.Millisecond, AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC), Usage: time.Duration(35) * time.Second, Supplier: "SUPPLIER1", DisconnectCause: "NORMAL_DISCONNECT", ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"}, CostSource: "", Cost: -1, }, &CDR{ CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), RunID: utils.META_DEFAULT, OriginHost: "127.0.0.1", Source: "testGetCDRs", OriginID: "testevent1", ToR: utils.VOICE, RequestType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC), PDD: time.Duration(20) * time.Millisecond, AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC), Usage: time.Duration(35) * time.Second, Supplier: "SUPPLIER1", DisconnectCause: "NORMAL_DISCONNECT", ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"}, CostSource: "testGetCDRs", Cost: 0.17, }, &CDR{ CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), RunID: "run2", OriginHost: "127.0.0.1", Source: "testGetCDRs", OriginID: "testevent1", ToR: utils.VOICE, RequestType: utils.META_RATED, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call_derived", Account: "1001", Subject: "1002", Destination: "1002", SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC), PDD: time.Duration(20) * time.Millisecond, AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC), Usage: time.Duration(35) * time.Second, Supplier: "SUPPLIER1", DisconnectCause: "NORMAL_DISCONNECT", ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"}, CostSource: "testGetCDRs", Cost: 0.17, }, &CDR{ CGRID: utils.Sha1("testevent2", time.Date(2015, 12, 29, 12, 58, 0, 0, time.UTC).String()), RunID: utils.META_DEFAULT, OriginHost: "192.168.1.12", Source: "testGetCDRs", OriginID: "testevent2", ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Direction: utils.OUT, Tenant: "itsyscom.com", Category: "call", Account: "1004", Subject: "1004", Destination: "1007", SetupTime: time.Date(2015, 12, 29, 12, 58, 0, 0, time.UTC), PDD: time.Duration(10) * time.Millisecond, AnswerTime: time.Date(2015, 12, 29, 12, 59, 0, 0, time.UTC), Usage: time.Duration(0) * time.Second, Supplier: "SUPPLIER1", DisconnectCause: "NO_ANSWER", ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"}, CostSource: "rater1", Cost: 0, }, &CDR{ CGRID: utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()), RunID: utils.MetaRaw, OriginHost: "192.168.1.13", Source: "testGetCDRs3", OriginID: "testevent3", ToR: utils.VOICE, RequestType: utils.META_PSEUDOPREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", Destination: "1003", SetupTime: time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC), PDD: time.Duration(20) * time.Millisecond, AnswerTime: time.Date(2015, 12, 28, 12, 58, 30, 0, time.UTC), Usage: time.Duration(125) * time.Second, Supplier: "SUPPLIER2", DisconnectCause: "NORMAL_DISCONNECT", ExtraFields: map[string]string{}, CostSource: "", Cost: -1, }, &CDR{ CGRID: utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()), RunID: utils.META_DEFAULT, OriginHost: "192.168.1.13", Source: "testGetCDRs3", OriginID: "testevent3", ToR: utils.VOICE, RequestType: utils.META_RATED, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1002", Destination: "1003", SetupTime: time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC), PDD: time.Duration(20) * time.Millisecond, AnswerTime: time.Date(2015, 12, 28, 12, 58, 30, 0, time.UTC), Usage: time.Duration(125) * time.Second, Supplier: "SUPPLIER2", DisconnectCause: "NORMAL_DISCONNECT", ExtraFields: map[string]string{}, CostSource: "testSetCDRs", Cost: -1, ExtraInfo: "AccountNotFound", }, &CDR{ CGRID: utils.Sha1("testevent4", time.Date(2015, 12, 14, 14, 52, 0, 0, time.UTC).String()), RunID: utils.MetaRaw, OriginHost: "192.168.1.14", Source: "testGetCDRs", OriginID: "testevent4", ToR: utils.VOICE, RequestType: utils.META_PSEUDOPREPAID, Direction: utils.OUT, Tenant: "itsyscom.com", Category: "call", Account: "1003", Subject: "1003", Destination: "1007", SetupTime: time.Date(2015, 12, 14, 14, 52, 0, 0, time.UTC), PDD: time.Duration(2) * time.Second, AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC), Usage: time.Duration(64) * time.Second, Supplier: "SUPPLIER1", DisconnectCause: "NORMAL_DISCONNECT", ExtraFields: map[string]string{"ExtraHeader3": "ExtraVal3"}, CostSource: "", Cost: -1, }, &CDR{ CGRID: utils.Sha1("testevent4", time.Date(2015, 12, 14, 14, 52, 0, 0, time.UTC).String()), RunID: utils.META_DEFAULT, OriginHost: "192.168.1.14", Source: "testGetCDRs", OriginID: "testevent4", ToR: utils.VOICE, RequestType: utils.META_RATED, Direction: utils.OUT, Tenant: "itsyscom.com", Category: "call", Account: "1003", Subject: "1003", Destination: "1007", SetupTime: time.Date(2015, 12, 14, 14, 52, 0, 0, time.UTC), PDD: time.Duration(2) * time.Second, AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC), Usage: time.Duration(64) * time.Second, Supplier: "SUPPLIER1", DisconnectCause: "NORMAL_DISCONNECT", ExtraFields: map[string]string{"ExtraHeader3": "ExtraVal3"}, CostSource: "testSetCDRs", Cost: 1.205, }, &CDR{ CGRID: utils.Sha1("testevent5", time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC).String()), RunID: utils.MetaRaw, OriginHost: "127.0.0.1", Source: "testGetCDRs5", OriginID: "testevent5", ToR: utils.SMS, RequestType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "sms", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC), PDD: time.Duration(0), AnswerTime: time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC), Usage: time.Duration(1) * time.Second, Supplier: "SUPPLIER3", DisconnectCause: "SENT_OK", ExtraFields: map[string]string{"Hdr4": "HdrVal4"}, CostSource: "", Cost: -1, }, &CDR{ CGRID: utils.Sha1("testevent5", time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC).String()), RunID: utils.META_DEFAULT, OriginHost: "127.0.0.1", Source: "testGetCDRs5", OriginID: "testevent5", ToR: utils.SMS, RequestType: utils.META_PREPAID, Direction: utils.OUT, Tenant: "cgrates.org", Category: "sms", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC), PDD: time.Duration(0), AnswerTime: time.Date(2015, 12, 15, 18, 22, 0, 0, time.UTC), Usage: time.Duration(1) * time.Second, Supplier: "SUPPLIER3", DisconnectCause: "SENT_OK", ExtraFields: map[string]string{"Hdr4": "HdrVal4"}, CostSource: "rater", Cost: 0.15, }, } // Store all CDRs for _, cdr := range cdrs { if err := cdrStorage.SetCDR(cdr, false); err != nil { return fmt.Errorf("CDR: %+v, SetCDR err: %s", cdr, err.Error()) } } // All CDRs, no filter if CDRs, _, err := cdrStorage.GetCDRs(new(utils.CDRsFilter), false); err != nil { return err } else if len(CDRs) != 10 { return fmt.Errorf("GetCDRs, unexpected number of CDRs returned: %d", len(CDRs)) } // Count ALL if CDRs, count, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Count: true}, false); err != nil { return err } else if len(CDRs) != 0 { return fmt.Errorf("CountCDRs, unexpected number of CDRs returned: %+v", CDRs) } else if count != 10 { return fmt.Errorf("CountCDRs, unexpected count of CDRs returned: %+v", count) } // Limit 5 if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}, false); err != nil { return err } else if len(CDRs) != 5 { return fmt.Errorf("Limit 5, unexpected number of CDRs returned: %+v", CDRs) } // Offset 5 if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}, false); err != nil { return err } else if len(CDRs) != 5 { return fmt.Errorf("Offset 5, unexpected number of CDRs returned: %+v", CDRs) } // Offset with limit 2 if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}, false); err != nil { return err } else if len(CDRs) != 2 { return fmt.Errorf("Offset with limit 2, unexpected number of CDRs returned: %+v", CDRs) } // Filter on cgrids if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{ utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()), }}, false); err != nil { return err } else if len(CDRs) != 5 { return fmt.Errorf("Filter on CGRIDs, unexpected number of CDRs returned: %+v", CDRs) } // Count on CGRIDS if _, count, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{ utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()), }, Count: true}, false); err != nil { return err } else if count != 5 { return fmt.Errorf("Count on CGRIDs, unexpected count of CDRs returned: %d", count) } // Filter on cgrids plus reqType if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{ utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()), }, RequestTypes: []string{utils.META_PREPAID}}, false); err != nil { return err } else if len(CDRs) != 2 { return fmt.Errorf("Filter on cgrids plus reqType, unexpected number of CDRs returned: %+v", CDRs) } // Count on multiple filter if _, count, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{ utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), utils.Sha1("testevent3", time.Date(2015, 12, 28, 12, 58, 0, 0, time.UTC).String()), }, RequestTypes: []string{utils.META_PREPAID}, Count: true}, false); err != nil { return err } else if count != 2 { return fmt.Errorf("Count on multiple filter, unexpected count of CDRs returned: %d", count) } // Filter on RunID if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RunIDs: []string{utils.DEFAULT_RUNID}}, false); err != nil { return err } else if len(CDRs) != 5 { return fmt.Errorf("Filter on RunID, unexpected number of CDRs returned: %+v", CDRs) } // Filter on TOR if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{ToRs: []string{utils.SMS}}, false); err != nil { return err } else if len(CDRs) != 2 { return fmt.Errorf("Filter on TOR, unexpected number of CDRs returned: %+v", CDRs) } // Filter on multiple TOR if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{ToRs: []string{utils.SMS, utils.VOICE}}, false); err != nil { return err } else if len(CDRs) != 10 { return fmt.Errorf("Filter on multiple TOR, unexpected number of CDRs returned: %+v", CDRs) } // Filter on OriginHost if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"127.0.0.1"}}, false); err != nil { return err } else if len(CDRs) != 5 { return fmt.Errorf("Filter on OriginHost, unexpected number of CDRs returned: %+v", CDRs) } // Filter on multiple OriginHost if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"127.0.0.1", "192.168.1.12"}}, false); err != nil { return err } else if len(CDRs) != 6 { return fmt.Errorf("Filter on OriginHosts, unexpected number of CDRs returned: %+v", CDRs) } // Filter on Source if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Sources: []string{"testGetCDRs"}}, false); err != nil { return err } else if len(CDRs) != 6 { return fmt.Errorf("Filter on Source, unexpected number of CDRs returned: %+v", CDRs) } // Filter on multiple Sources if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Sources: []string{"testGetCDRs", "testGetCDRs5"}}, false); err != nil { return err } else if len(CDRs) != 8 { return fmt.Errorf("Filter on Sources, unexpected number of CDRs returned: %+v", CDRs) } // Filter on reqType if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID}}, false); err != nil { return err } else if len(CDRs) != 4 { return fmt.Errorf("Filter on RequestType, unexpected number of CDRs returned: %+v", len(CDRs)) } // Filter on multiple reqType if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}, false); err != nil { return err } else if len(CDRs) != 6 { return fmt.Errorf("Filter on RequestTypes, unexpected number of CDRs returned: %+v", CDRs) } // Filter on direction if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Directions: []string{utils.OUT}}, false); err != nil { return err } else if len(CDRs) != 10 { return fmt.Errorf("Filter on Direction, unexpected number of CDRs returned: %+v", CDRs) } // Filter on Tenant if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com"}}, false); err != nil { return err } else if len(CDRs) != 3 { return fmt.Errorf("Filter on Tenant, unexpected number of CDRs returned: %+v", CDRs) } // Filter on multiple tenants if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}, false); err != nil { return err } else if len(CDRs) != 10 { return fmt.Errorf("Filter on Tenants, Unexpected number of CDRs returned: %+v", CDRs) } // Filter on Category if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Categories: []string{"call"}}, false); err != nil { return err } else if len(CDRs) != 7 { return fmt.Errorf("Filter on Category, unexpected number of CDRs returned: %+v", CDRs) } // Filter on multiple categories if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Categories: []string{"sms", "call_derived"}}, false); err != nil { return err } else if len(CDRs) != 3 { return fmt.Errorf("Filter on Categories, unexpected number of CDRs returned: %+v", CDRs) } // Filter on account if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1002"}}, false); err != nil { return err } else if len(CDRs) != 2 { return fmt.Errorf("Filter on Account, unexpected number of CDRs returned: %+v", CDRs) } // Filter on multiple account if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1001", "1002"}}, false); err != nil { return err } else if len(CDRs) != 7 { return fmt.Errorf("Filter on Accounts, unexpected number of CDRs returned: %+v", CDRs) } // Filter on subject if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1004"}}, false); err != nil { return err } else if len(CDRs) != 1 { return fmt.Errorf("Filter on Subject, unexpected number of CDRs returned: %+v", CDRs) } // Filter on multiple subject if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1002", "1003"}}, false); err != nil { return err } else if len(CDRs) != 5 { return fmt.Errorf("Filter on Subjects, unexpected number of CDRs returned: %+v", CDRs) } // Filter on destPrefix if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"10"}}, false); err != nil { return err } else if len(CDRs) != 10 { return fmt.Errorf("Filter on DestinationPrefix, unexpected number of CDRs returned: %+v", CDRs) } // Filter on multiple destPrefixes if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"1002", "1003"}}, false); err != nil { return err } else if len(CDRs) != 7 { return fmt.Errorf("Filter on DestinationPrefix, unexpected number of CDRs returned: %+v", CDRs) } // Filter on not destPrefix if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{NotDestinationPrefixes: []string{"10"}}, false); err != nil { return err } else if len(CDRs) != 0 { return fmt.Errorf("Filter on NotDestinationPrefix, unexpected number of CDRs returned: %+v", CDRs) } // Filter on not destPrefixes if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{NotDestinationPrefixes: []string{"1001", "1002"}}, false); err != nil { return err } else if len(CDRs) != 5 { return fmt.Errorf("Filter on NotDestinationPrefix, unexpected number of CDRs returned: %+v", CDRs) } // Filter on hasPrefix and not HasPrefix if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"1002", "1003"}, NotDestinationPrefixes: []string{"1002"}}, false); err != nil { return err } else if len(CDRs) != 2 { return fmt.Errorf("Filter on DestinationPrefix and NotDestinationPrefix, unexpected number of CDRs returned: %+v", CDRs) } // Filter on MaxCost var orderIdStart, orderIdEnd int64 // Capture also orderIds for the next test if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{MaxCost: utils.Float64Pointer(0.0)}, false); err != nil { return err } else if len(CDRs) != 5 { return fmt.Errorf("Filter on MaxCost, unexpected number of CDRs returned: ", CDRs) } else { for i, cdr := range CDRs { if i == 0 { orderIdStart = cdr.OrderID } if cdr.OrderID < orderIdStart { orderIdStart = cdr.OrderID } if cdr.OrderID > orderIdEnd { orderIdEnd = cdr.OrderID } } } // Filter on orderIdStart if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{OrderIDStart: &orderIdStart}, false); err != nil { return err } else if len(CDRs) != 10 { return fmt.Errorf("Filter on OrderIDStart, unexpected number of CDRs returned: %d", len(CDRs)) } // Filter on orderIdStart and orderIdEnd if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{OrderIDStart: &orderIdStart, OrderIDEnd: &orderIdEnd}, false); err != nil { return err } else if len(CDRs) != 8 { return fmt.Errorf("Filter on OrderIDStart OrderIDEnd, unexpected number of CDRs returned: %d", len(CDRs)) } var timeStart, timeEnd time.Time // Filter on timeStart timeStart = time.Date(2015, 12, 28, 0, 0, 0, 0, time.UTC) if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart}, false); err != nil { return err } else if len(CDRs) != 3 { return fmt.Errorf("Filter on AnswerTimeStart, unexpected number of CDRs returned: %d", len(CDRs)) } // Filter on timeStart and timeEnd timeEnd = time.Date(2015, 12, 29, 0, 0, 0, 0, time.UTC) if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}, false); err != nil { return err } else if len(CDRs) != 2 { return fmt.Errorf("Filter on AnswerTimeStart AnswerTimeEnd, unexpected number of CDRs returned: %+v", CDRs) } // Filter on MinPDD if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{MinPDD: "20ms"}, false); err != nil { return err } else if len(CDRs) != 7 { return fmt.Errorf("Filter on MinPDD, unexpected number of CDRs returned: %+v", CDRs) } // Filter on maxPdd if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{MaxPDD: "1s"}, false); err != nil { return err } else if len(CDRs) != 8 { return fmt.Errorf("Filter on MaxPDD, unexpected number of CDRs returned: %+v", CDRs) } // Filter on minPdd, maxPdd if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{MinPDD: "10ms", MaxPDD: "1s"}, false); err != nil { return err } else if len(CDRs) != 6 { return fmt.Errorf("Filter on MinPDD MaxPDD, unexpected number of CDRs returned: %+v", CDRs) } // Combined filter if CDRs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}, false); err != nil { return err } else if len(CDRs) != 1 { return fmt.Errorf("Filter on RequestTypes AnswerTimeStart AnswerTimeEnd, unexpected number of CDRs returned: %+v", CDRs) } // Remove CDRs if _, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}, true); err != nil { return err } // All CDRs, no filter if cdrs, _, err := cdrStorage.GetCDRs(new(utils.CDRsFilter), false); err != nil { return err } else if len(cdrs) != 9 { return fmt.Errorf("GetCDRs, unexpected number of CDRs returned after remove: %d", len(cdrs)) } return nil }
func TestPSQLGetStoredCdrs(t *testing.T) { if !*testLocal { return } var timeStart, timeEnd time.Time // All CDRs, no filter if storedCdrs, _, err := psqlDb.GetStoredCdrs(new(utils.CdrsFilter)); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Count ALL if storedCdrs, count, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Count: true}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 0 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } else if count != 8 { t.Error("Unexpected count of StoredCdrs returned: ", count) } // Limit 5 if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 5 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Offset 5 if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 5 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Offset with limit 2 if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs)) } // Filter on cgrids if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Count on CGRIDS if _, count, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, Count: true}); err != nil { t.Error(err.Error()) } else if count != 2 { t.Error("Unexpected count of StoredCdrs returned: ", count) } // Filter on cgrids plus reqType if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{utils.META_PREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Count on multiple filter if _, count, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CgrIds: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, ReqTypes: []string{utils.META_PREPAID}, Count: true}); err != nil { t.Error(err.Error()) } else if count != 1 { t.Error("Unexpected count of StoredCdrs returned: ", count) } // Filter on runId if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{RunIds: []string{utils.DEFAULT_RUNID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on TOR if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Tors: []string{utils.SMS}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 0 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple TOR if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Tors: []string{utils.SMS, utils.VOICE}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on cdrHost if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrHosts: []string{"192.168.1.2"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 3 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple cdrHost if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrHosts: []string{"192.168.1.1", "192.168.1.2"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on cdrSource if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrSources: []string{"UNKNOWN"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple cdrSource if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{CdrSources: []string{"UNKNOWN", "UNKNOWN2"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on reqType if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_PREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple reqType if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 3 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on direction if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Directions: []string{"*out"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on tenant if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Tenants: []string{"itsyscom.com"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 3 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple tenants if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on category if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Categories: []string{"premium_call"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple categories if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Categories: []string{"premium_call", "call"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on account if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Accounts: []string{"1002"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 3 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple account if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Accounts: []string{"1001", "1002"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on subject if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Subjects: []string{"1000"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple subject if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{Subjects: []string{"1000", "1002"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 3 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on destPrefix if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{DestPrefixes: []string{"+498651"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 3 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on multiple destPrefixes if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{DestPrefixes: []string{"1001", "+498651"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 4 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on ratedAccount if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{RatedAccounts: []string{"8001"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on ratedSubject if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{RatedSubjects: []string{"91001"}}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on ignoreRated var orderIdStart, orderIdEnd int64 // Capture also orderIds for the next test if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{MaxCost: utils.Float64Pointer(0.0)}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 5 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } else { for _, cdr := range storedCdrs { if cdr.OrderId < orderIdStart { orderIdStart = cdr.OrderId } if cdr.OrderId > orderIdEnd { orderIdEnd = cdr.OrderId } } } // Filter on orderIdStart if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 8 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on orderIdStart and orderIdEnd if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{OrderIdStart: orderIdStart, OrderIdEnd: orderIdEnd}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 4 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on timeStart timeStart = time.Date(2013, 11, 8, 8, 0, 0, 0, time.UTC) if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 5 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on timeStart and timeEnd timeEnd = time.Date(2013, 12, 1, 8, 0, 0, 0, time.UTC) if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 2 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on minPdd if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(3)}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 7 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on maxPdd if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{MaxPdd: utils.Float64Pointer(3)}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on minPdd, maxPdd if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{MinPdd: utils.Float64Pointer(3), MaxPdd: utils.Float64Pointer(5)}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 5 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Combined filter if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{ReqTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 1 { t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } // Filter on ignoreDerived if storedCdrs, _, err := psqlDb.GetStoredCdrs(&utils.CdrsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, FilterOnRated: true}); err != nil { t.Error(err.Error()) } else if len(storedCdrs) != 0 { // ToDo: Recheck this value t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) } }
func GetUB() *Account { uc := &UnitCounter{ Counters: CounterFilters{&CounterFilter{Value: 1}, &CounterFilter{Filter: &BalanceFilter{Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT"))}}, &CounterFilter{Filter: &BalanceFilter{Weight: utils.Float64Pointer(10), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET"))}}}, } at := &ActionTrigger{ ID: "some_uuid", ThresholdValue: 100.0, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), }, Weight: 10.0, ActionsID: "Commando", } var zeroTime time.Time zeroTime = zeroTime.UTC() // for deep equal to find location ub := &Account{ ID: "rif", AllowNegative: true, BalanceMap: map[string]Balances{utils.SMS: Balances{&Balance{Value: 14, ExpirationDate: zeroTime}}, utils.DATA: Balances{&Balance{Value: 1024, ExpirationDate: zeroTime}}, utils.VOICE: Balances{&Balance{Weight: 20, DestinationIDs: utils.NewStringMap("NAT")}, &Balance{Weight: 10, DestinationIDs: utils.NewStringMap("RET")}}}, UnitCounters: UnitCounters{utils.SMS: []*UnitCounter{uc, uc}}, ActionTriggers: ActionTriggers{at, at, at}, } return ub }
func TestSMGVoiceSessionTTLWithRelocate(t *testing.T) { if !*testIntegration { return } attrSetBalance := utils.AttrSetBalance{Tenant: "cgrates.org", Account: "TestTTLWithRelocate", BalanceType: utils.VOICE, BalanceID: utils.StringPointer("TestTTLWithRelocate"), Value: utils.Float64Pointer(300), RatingSubject: utils.StringPointer("*zero50ms")} var reply string if err := smgRPC.Call("ApierV2.SetBalance", attrSetBalance, &reply); err != nil { t.Error(err) } else if reply != utils.OK { t.Errorf("Received: %s", reply) } var acnt *engine.Account attrs := &utils.AttrGetAccount{Tenant: attrSetBalance.Tenant, Account: attrSetBalance.Account} eAcntVal := 300.0 if err := smgRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil { t.Error(err) } else if acnt.BalanceMap[utils.VOICE].GetTotalValue() != eAcntVal { t.Errorf("Expecting: %f, received: %f", eAcntVal, acnt.BalanceMap[utils.VOICE].GetTotalValue()) } smgEv := SMGenericEvent{ utils.EVENT_NAME: "TEST_EVENT_SESSION_TTL_RELOCATE", utils.TOR: utils.VOICE, utils.ACCID: "12361", utils.DIRECTION: utils.OUT, utils.ACCOUNT: "TestTTLWithRelocate", utils.SUBJECT: "TestTTLWithRelocate", utils.DESTINATION: "1009", utils.CATEGORY: "call", utils.TENANT: "cgrates.org", utils.REQTYPE: utils.META_PREPAID, utils.SETUP_TIME: "2016-01-05 18:30:49", utils.ANSWER_TIME: "2016-01-05 18:31:05", utils.USAGE: "2m", } var maxUsage float64 if err := smgRPC.Call("SMGenericV1.InitiateSession", smgEv, &maxUsage); err != nil { t.Error(err) } if maxUsage != 120 { t.Error("Bad max usage: ", maxUsage) } eAcntVal = 180.0 if err := smgRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil { t.Error(err) } else if acnt.BalanceMap[utils.VOICE].GetTotalValue() != eAcntVal { t.Errorf("Expecting: %f, received: %f", eAcntVal, acnt.BalanceMap[utils.VOICE].GetTotalValue()) } var aSessions []*ActiveSession if err := smgRPC.Call("SMGenericV1.ActiveSessions", utils.AttrSMGGetActiveSessions{RunID: utils.StringPointer(utils.META_DEFAULT), OriginID: utils.StringPointer(smgEv.GetUUID())}, &aSessions); err != nil { t.Error(err) } else if len(aSessions) != 1 { t.Errorf("Unexpected number of sessions received: %+v", aSessions) } else if aSessions[0].Usage != time.Duration(120)*time.Second { t.Errorf("Expecting 2m, received usage: %v", aSessions[0].Usage) } smgEv = SMGenericEvent{ utils.EVENT_NAME: smgEv[utils.EVENT_NAME], utils.TOR: smgEv[utils.TOR], utils.InitialOriginID: smgEv[utils.ACCID], utils.ACCID: "12362", utils.DIRECTION: smgEv[utils.DIRECTION], utils.ACCOUNT: smgEv[utils.ACCOUNT], utils.SUBJECT: smgEv[utils.SUBJECT], utils.DESTINATION: smgEv[utils.DESTINATION], utils.CATEGORY: smgEv[utils.CATEGORY], utils.TENANT: smgEv[utils.TENANT], utils.REQTYPE: smgEv[utils.REQTYPE], utils.USAGE: "2m", utils.LastUsed: "30s", } if err := smgRPC.Call("SMGenericV1.UpdateSession", smgEv, &maxUsage); err != nil { t.Error(err) } if maxUsage != 120 { t.Error("Bad max usage: ", maxUsage) } eAcntVal = 150.0 if err := smgRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil { t.Error(err) } else if acnt.BalanceMap[utils.VOICE].GetTotalValue() != eAcntVal { t.Errorf("Expecting: %f, received: %f", eAcntVal, acnt.BalanceMap[utils.VOICE].GetTotalValue()) } if err := smgRPC.Call("SMGenericV1.ActiveSessions", utils.AttrSMGGetActiveSessions{RunID: utils.StringPointer(utils.META_DEFAULT), OriginID: utils.StringPointer(smgEv.GetUUID())}, &aSessions); err != nil { t.Error(err) } else if len(aSessions) != 1 { t.Errorf("Unexpected number of sessions received: %+v", aSessions) } else if aSessions[0].Usage != time.Duration(150)*time.Second { t.Errorf("Expecting 2m30s, received usage: %v", aSessions[0].Usage) } time.Sleep(100 * time.Millisecond) eAcntVal = 149.95 if err := smgRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil { t.Error(err) } else if acnt.BalanceMap[utils.VOICE].GetTotalValue() != eAcntVal { t.Errorf("Expecting: %f, received: %f", eAcntVal, acnt.BalanceMap[utils.VOICE].GetTotalValue()) } if err := smgRPC.Call("SMGenericV1.ActiveSessions", utils.AttrSMGGetActiveSessions{RunID: utils.StringPointer(utils.META_DEFAULT), OriginID: utils.StringPointer(smgEv.GetUUID())}, &aSessions); err != nil { t.Error(err) } else if len(aSessions) != 0 { t.Errorf("Unexpected number of sessions received: %+v", aSessions) } var cdrs []*engine.ExternalCDR req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, DestinationPrefixes: []string{smgEv.GetDestination(utils.META_DEFAULT)}} if err := smgRPC.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(cdrs) != 1 { t.Error("Unexpected number of CDRs returned: ", len(cdrs)) } else { if cdrs[0].Usage != "150.05" { t.Errorf("Unexpected CDR Usage received, cdr: %v %+v ", cdrs[0].Usage, cdrs[0]) } } }
func TestDfCdrcJsonCfg(t *testing.T) { eFields := []*CdrFieldJsonCfg{} cdrFields := []*CdrFieldJsonCfg{ &CdrFieldJsonCfg{Tag: utils.StringPointer("TOR"), Field_id: utils.StringPointer(utils.TOR), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("2"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("OriginID"), Field_id: utils.StringPointer(utils.ACCID), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("3"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"), Field_id: utils.StringPointer(utils.REQTYPE), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("4"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), Field_id: utils.StringPointer(utils.DIRECTION), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("5"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), Field_id: utils.StringPointer(utils.TENANT), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("6"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Category"), Field_id: utils.StringPointer(utils.CATEGORY), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("7"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Account"), Field_id: utils.StringPointer(utils.ACCOUNT), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("8"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"), Field_id: utils.StringPointer(utils.SUBJECT), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("9"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"), Field_id: utils.StringPointer(utils.DESTINATION), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("10"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("SetupTime"), Field_id: utils.StringPointer(utils.SETUP_TIME), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("11"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("AnswerTime"), Field_id: utils.StringPointer(utils.ANSWER_TIME), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("12"), Mandatory: utils.BoolPointer(true)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Usage"), Field_id: utils.StringPointer(utils.USAGE), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer("13"), Mandatory: utils.BoolPointer(true)}, } cacheDumpFields := []*CdrFieldJsonCfg{ &CdrFieldJsonCfg{Tag: utils.StringPointer("CGRID"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.CGRID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("RunID"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.MEDI_RUNID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("TOR"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.TOR)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("OriginID"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.ACCID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.REQTYPE)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.DIRECTION)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.TENANT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Category"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.CATEGORY)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Account"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.ACCOUNT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.SUBJECT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.DESTINATION)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("SetupTime"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.SETUP_TIME), Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")}, &CdrFieldJsonCfg{Tag: utils.StringPointer("AnswerTime"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.ANSWER_TIME), Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Usage"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.USAGE)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Cost"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.COST)}, } eCfg := []*CdrcJsonCfg{ &CdrcJsonCfg{ Id: utils.StringPointer(utils.META_DEFAULT), Enabled: utils.BoolPointer(false), Dry_run: utils.BoolPointer(false), Cdrs_conns: &[]*HaPoolJsonCfg{&HaPoolJsonCfg{ Address: utils.StringPointer(utils.MetaInternal), }}, Cdr_format: utils.StringPointer("csv"), Field_separator: utils.StringPointer(","), Timezone: utils.StringPointer(""), Run_delay: utils.IntPointer(0), Max_open_files: utils.IntPointer(1024), Data_usage_multiply_factor: utils.Float64Pointer(1024.0), Cdr_in_dir: utils.StringPointer("/var/spool/cgrates/cdrc/in"), Cdr_out_dir: utils.StringPointer("/var/spool/cgrates/cdrc/out"), Failed_calls_prefix: utils.StringPointer("missed_calls"), Cdr_path: utils.StringPointer(""), Cdr_source_id: utils.StringPointer("freeswitch_csv"), Cdr_filter: utils.StringPointer(""), Continue_on_success: utils.BoolPointer(false), Partial_record_cache: utils.StringPointer("10s"), Partial_cache_expiry_action: utils.StringPointer(utils.MetaDumpToFile), Header_fields: &eFields, Content_fields: &cdrFields, Trailer_fields: &eFields, Cache_dump_fields: &cacheDumpFields, }, } if cfg, err := dfCgrJsonCfg.CdrcJsonCfg(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfg, cfg) { t.Errorf("Expecting: \n%s\n, received: \n%s\n: ", utils.ToIJSON(eCfg), utils.ToIJSON(cfg)) } }
func TestDfCdreJsonCfgs(t *testing.T) { eFields := []*CdrFieldJsonCfg{} eContentFlds := []*CdrFieldJsonCfg{ &CdrFieldJsonCfg{Tag: utils.StringPointer("CGRID"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.CGRID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("RunID"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.MEDI_RUNID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("TOR"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.TOR)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("OriginID"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.ACCID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("RequestType"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.REQTYPE)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.DIRECTION)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.TENANT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Category"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.CATEGORY)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Account"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.ACCOUNT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.SUBJECT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.DESTINATION)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("SetupTime"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.SETUP_TIME), Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")}, &CdrFieldJsonCfg{Tag: utils.StringPointer("AnswerTime"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.ANSWER_TIME), Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Usage"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.USAGE)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Cost"), Type: utils.StringPointer(utils.META_COMPOSED), Value: utils.StringPointer(utils.COST), Rounding_decimals: utils.IntPointer(4)}, } eCfg := map[string]*CdreJsonCfg{ utils.META_DEFAULT: &CdreJsonCfg{ Cdr_format: utils.StringPointer("csv"), Field_separator: utils.StringPointer(","), Data_usage_multiply_factor: utils.Float64Pointer(1.0), Sms_usage_multiply_factor: utils.Float64Pointer(1.0), Mms_usage_multiply_factor: utils.Float64Pointer(1.0), Generic_usage_multiply_factor: utils.Float64Pointer(1.0), Cost_multiply_factor: utils.Float64Pointer(1.0), Export_directory: utils.StringPointer("/var/spool/cgrates/cdre"), Header_fields: &eFields, Content_fields: &eContentFlds, Trailer_fields: &eFields, }, } if cfg, err := dfCgrJsonCfg.CdreJsonCfgs(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfg, cfg) { expect, _ := json.Marshal(eCfg) received, _ := json.Marshal(cfg) t.Errorf("Expecting: %s, received: %s", string(expect), string(received)) } }
func (mig MigratorRC8) migrateActionsInt() error { keys, err := mig.db.Cmd("KEYS", utils.ACTION_PREFIX+"*").List() if err != nil { return err } newAcsMap := make(map[string]engine.Actions, len(keys)) for _, key := range keys { log.Printf("Migrating action: %s...", key) var oldAcs Actions1 var values []byte if values, err = mig.db.Cmd("GET", key).Bytes(); err == nil { if err := mig.ms.Unmarshal(values, &oldAcs); err != nil { return err } } newAcs := make(engine.Actions, len(oldAcs)) for index, oldAc := range oldAcs { a := &engine.Action{ Id: oldAc.Id, ActionType: oldAc.ActionType, ExtraParameters: oldAc.ExtraParameters, ExpirationString: oldAc.ExpirationString, Filter: oldAc.Filter, Weight: oldAc.Weight, Balance: &engine.BalanceFilter{}, } bf := a.Balance if oldAc.Balance.Uuid != "" { bf.Uuid = utils.StringPointer(oldAc.Balance.Uuid) } if oldAc.Balance.Id != "" { bf.ID = utils.StringPointer(oldAc.Balance.Id) } if oldAc.BalanceType != "" { bf.Type = utils.StringPointer(oldAc.BalanceType) } if oldAc.Balance.Value != 0 { bf.Value = &utils.ValueFormula{Static: oldAc.Balance.Value} } if oldAc.Balance.RatingSubject != "" { bf.RatingSubject = utils.StringPointer(oldAc.Balance.RatingSubject) } if !oldAc.Balance.DestinationIds.IsEmpty() { bf.DestinationIDs = utils.StringMapPointer(oldAc.Balance.DestinationIds) } if !oldAc.Balance.TimingIDs.IsEmpty() { bf.TimingIDs = utils.StringMapPointer(oldAc.Balance.TimingIDs) } if !oldAc.Balance.Categories.IsEmpty() { bf.Categories = utils.StringMapPointer(oldAc.Balance.Categories) } if !oldAc.Balance.SharedGroups.IsEmpty() { bf.SharedGroups = utils.StringMapPointer(oldAc.Balance.SharedGroups) } if oldAc.Balance.Weight != 0 { bf.Weight = utils.Float64Pointer(oldAc.Balance.Weight) } if oldAc.Balance.Disabled != false { bf.Disabled = utils.BoolPointer(oldAc.Balance.Disabled) } if !oldAc.Balance.ExpirationDate.IsZero() { bf.ExpirationDate = utils.TimePointer(oldAc.Balance.ExpirationDate) } bf.Timings = oldAc.Balance.Timings newAcs[index] = a } newAcsMap[key] = newAcs } // write data back for key, acs := range newAcsMap { result, err := mig.ms.Marshal(&acs) if err != nil { return err } if err = mig.db.Cmd("SET", key, result).Err; err != nil { return err } } return nil }
func TestUnitCountersKeepValuesAfterInit(t *testing.T) { a := &Account{ ActionTriggers: ActionTriggers{ &ActionTrigger{ UniqueID: "TestTR1", ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR11", ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(20), }, }, &ActionTrigger{ UniqueID: "TestTR2", ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.VOICE), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR22", ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.VOICE), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET")), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR3", ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.VOICE), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR4", ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.SMS), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR5", ThresholdType: utils.TRIGGER_MAX_BALANCE, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.SMS), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), Weight: utils.Float64Pointer(10), }, }, }, } a.InitCounters() a.UnitCounters.addUnits(10, utils.VOICE, &CallCost{Destination: "0723045326"}, nil) if len(a.UnitCounters) != 3 || len(a.UnitCounters[utils.VOICE][0].Counters) != 2 || a.UnitCounters[utils.VOICE][0].Counters[0].Value != 10 || a.UnitCounters[utils.VOICE][0].Counters[1].Value != 10 { for key, counters := range a.UnitCounters { t.Log(key) for _, uc := range counters { t.Logf("UC: %+v", uc) for _, b := range uc.Counters { t.Logf("B: %+v", b) } } } t.Errorf("Error adding unit counters: %v", len(a.UnitCounters)) } a.InitCounters() if len(a.UnitCounters) != 3 || len(a.UnitCounters[utils.VOICE][0].Counters) != 2 || a.UnitCounters[utils.VOICE][0].Counters[0].Value != 10 || a.UnitCounters[utils.VOICE][0].Counters[1].Value != 10 { for key, counters := range a.UnitCounters { t.Log(key) for _, uc := range counters { t.Logf("UC: %+v", uc) for _, b := range uc.Counters { t.Logf("B: %+v", b) } } } t.Errorf("Error keeping counter values after init: %v", len(a.UnitCounters)) } }
func TestDfCdreJsonCfgs(t *testing.T) { eFields := []*CdrFieldJsonCfg{} eContentFlds := []*CdrFieldJsonCfg{ &CdrFieldJsonCfg{Tag: utils.StringPointer("CgrId"), Cdr_field_id: utils.StringPointer(utils.CGRID), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.CGRID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("RunId"), Cdr_field_id: utils.StringPointer(utils.MEDI_RUNID), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.MEDI_RUNID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Tor"), Cdr_field_id: utils.StringPointer(utils.TOR), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.TOR)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("AccId"), Cdr_field_id: utils.StringPointer(utils.ACCID), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.ACCID)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("ReqType"), Cdr_field_id: utils.StringPointer(utils.REQTYPE), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.REQTYPE)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Direction"), Cdr_field_id: utils.StringPointer(utils.DIRECTION), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.DIRECTION)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Tenant"), Cdr_field_id: utils.StringPointer(utils.TENANT), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.TENANT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Category"), Cdr_field_id: utils.StringPointer(utils.CATEGORY), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.CATEGORY)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Account"), Cdr_field_id: utils.StringPointer(utils.ACCOUNT), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.ACCOUNT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Subject"), Cdr_field_id: utils.StringPointer(utils.SUBJECT), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.SUBJECT)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Destination"), Cdr_field_id: utils.StringPointer(utils.DESTINATION), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.DESTINATION)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("SetupTime"), Cdr_field_id: utils.StringPointer(utils.SETUP_TIME), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.SETUP_TIME), Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")}, &CdrFieldJsonCfg{Tag: utils.StringPointer("AnswerTime"), Cdr_field_id: utils.StringPointer(utils.ANSWER_TIME), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.ANSWER_TIME), Layout: utils.StringPointer("2006-01-02T15:04:05Z07:00")}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Usage"), Cdr_field_id: utils.StringPointer(utils.USAGE), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.USAGE)}, &CdrFieldJsonCfg{Tag: utils.StringPointer("Cost"), Cdr_field_id: utils.StringPointer(utils.COST), Type: utils.StringPointer("cdrfield"), Value: utils.StringPointer(utils.COST)}, } eCfg := map[string]*CdreJsonCfg{ utils.META_DEFAULT: &CdreJsonCfg{ Cdr_format: utils.StringPointer("csv"), Field_separator: utils.StringPointer(","), Data_usage_multiply_factor: utils.Float64Pointer(1.0), Sms_usage_multiply_factor: utils.Float64Pointer(1.0), Generic_usage_multiply_factor: utils.Float64Pointer(1.0), Cost_multiply_factor: utils.Float64Pointer(1.0), Cost_rounding_decimals: utils.IntPointer(-1), Cost_shift_digits: utils.IntPointer(0), Mask_destination_id: utils.StringPointer("MASKED_DESTINATIONS"), Mask_length: utils.IntPointer(0), Export_dir: utils.StringPointer("/var/log/cgrates/cdre"), Header_fields: &eFields, Content_fields: &eContentFlds, Trailer_fields: &eFields, }, } if cfg, err := dfCgrJsonCfg.CdreJsonCfgs(); err != nil { t.Error(err) } else if !reflect.DeepEqual(eCfg, cfg) { t.Error("Received: ", cfg) } }
func TestUnitsCounterAddBalanceExists(t *testing.T) { uc := &UnitCounter{ Counters: CounterFilters{&CounterFilter{Value: 1}, &CounterFilter{Value: 10, Filter: &BalanceFilter{Weight: utils.Float64Pointer(20), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT"))}}, &CounterFilter{Filter: &BalanceFilter{Weight: utils.Float64Pointer(10), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("RET"))}}}, } UnitCounters{utils.SMS: []*UnitCounter{uc}}.addUnits(5, utils.SMS, &CallCost{Destination: "0723"}, nil) if len(uc.Counters) != 3 || uc.Counters[1].Value != 15 { t.Error("Error adding minute bucket!") } }
func TestUnitCountersCountAllMonetary(t *testing.T) { a := &Account{ ActionTriggers: ActionTriggers{ &ActionTrigger{ UniqueID: "TestTR1", ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT, utils.IN)), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR11", ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.MONETARY), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT, utils.IN)), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR2", ThresholdType: utils.TRIGGER_MAX_EVENT_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.VOICE), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT, utils.IN)), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR3", ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.VOICE), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT, utils.IN)), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR4", ThresholdType: utils.TRIGGER_MAX_BALANCE_COUNTER, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.SMS), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT, utils.IN)), Weight: utils.Float64Pointer(10), }, }, &ActionTrigger{ UniqueID: "TestTR5", ThresholdType: utils.TRIGGER_MAX_BALANCE, Balance: &BalanceFilter{ Type: utils.StringPointer(utils.SMS), Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT, utils.IN)), Weight: utils.Float64Pointer(10), }, }, }, } a.InitCounters() a.UnitCounters.addUnits(10, utils.MONETARY, &CallCost{}, nil) if len(a.UnitCounters) != 3 || len(a.UnitCounters[utils.MONETARY][0].Counters) != 2 || a.UnitCounters[utils.MONETARY][0].Counters[0].Value != 10 || a.UnitCounters[utils.MONETARY][0].Counters[1].Value != 10 { for key, counters := range a.UnitCounters { t.Log(key) for _, uc := range counters { t.Logf("UC: %+v", uc) for _, b := range uc.Counters { t.Logf("B: %+v", b) } } } t.Errorf("Error Initializing adding unit counters: %v", len(a.UnitCounters)) } }
func (mig MigratorRC8) migrateActionTriggersInt() error { keys, err := mig.db.Cmd("KEYS", utils.ACTION_TRIGGER_PREFIX+"*").List() if err != nil { return err } newAtrsMap := make(map[string]engine.ActionTriggers, len(keys)) for _, key := range keys { log.Printf("Migrating action trigger: %s...", key) var oldAtrs ActionTriggers1 var values []byte if values, err = mig.db.Cmd("GET", key).Bytes(); err == nil { if err := mig.ms.Unmarshal(values, &oldAtrs); err != nil { return err } } newAtrs := make(engine.ActionTriggers, len(oldAtrs)) for index, oldAtr := range oldAtrs { at := &engine.ActionTrigger{ ID: oldAtr.ID, UniqueID: oldAtr.UniqueID, ThresholdType: oldAtr.ThresholdType, ThresholdValue: oldAtr.ThresholdValue, Recurrent: oldAtr.Recurrent, MinSleep: oldAtr.MinSleep, Weight: oldAtr.Weight, ActionsID: oldAtr.ActionsId, MinQueuedItems: oldAtr.MinQueuedItems, Executed: oldAtr.Executed, } bf := &engine.BalanceFilter{} if oldAtr.BalanceId != "" { bf.ID = utils.StringPointer(oldAtr.BalanceId) } if oldAtr.BalanceType != "" { bf.Type = utils.StringPointer(oldAtr.BalanceType) } if oldAtr.BalanceRatingSubject != "" { bf.RatingSubject = utils.StringPointer(oldAtr.BalanceRatingSubject) } if !oldAtr.BalanceDirections.IsEmpty() { bf.Directions = utils.StringMapPointer(oldAtr.BalanceDirections) } if !oldAtr.BalanceDestinationIds.IsEmpty() { bf.DestinationIDs = utils.StringMapPointer(oldAtr.BalanceDestinationIds) } if !oldAtr.BalanceTimingTags.IsEmpty() { bf.TimingIDs = utils.StringMapPointer(oldAtr.BalanceTimingTags) } if !oldAtr.BalanceCategories.IsEmpty() { bf.Categories = utils.StringMapPointer(oldAtr.BalanceCategories) } if !oldAtr.BalanceSharedGroups.IsEmpty() { bf.SharedGroups = utils.StringMapPointer(oldAtr.BalanceSharedGroups) } if oldAtr.BalanceWeight != 0 { bf.Weight = utils.Float64Pointer(oldAtr.BalanceWeight) } if oldAtr.BalanceDisabled != false { bf.Disabled = utils.BoolPointer(oldAtr.BalanceDisabled) } if !oldAtr.BalanceExpirationDate.IsZero() { bf.ExpirationDate = utils.TimePointer(oldAtr.BalanceExpirationDate) } at.Balance = bf newAtrs[index] = at } newAtrsMap[key] = newAtrs } // write data back for key, atrs := range newAtrsMap { result, err := mig.ms.Marshal(&atrs) if err != nil { return err } if err = mig.db.Cmd("SET", key, result).Err; err != nil { return err } } return nil }