示例#1
0
文件: cdrs.go 项目: gale320/cgrates
// 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
}
示例#2
0
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)
	}
}
示例#3
0
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)
	}
}
示例#5
0
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)
	}
}
示例#6
0
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)
	}
}
示例#7
0
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)
	}
}
示例#8
0
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)
	}
}
示例#9
0
// 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
}
示例#10
0
文件: cdrs.go 项目: perrault/cgrates
// 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
}
示例#11
0
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"])
	}
}
示例#12
0
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])
	}
}
示例#13
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)
	}
}
示例#14
0
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)
	}
}
示例#15
0
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)
	}
}
示例#16
0
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)
	}
}
示例#17
0
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
}
示例#18
0
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)
	}
}
示例#19
0
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)
	}
}
示例#21
0
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
}
示例#22
0
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])
		}
	}

}
示例#23
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))
	}
}
示例#24
0
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))
	}
}
示例#25
0
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
}
示例#26
0
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))
	}
}
示例#27
0
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)
	}
}
示例#28
0
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!")
	}
}
示例#29
0
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))
	}
}
示例#30
0
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
}