示例#1
0
func TestGetCostMaxDebitRoundingIssue(t *testing.T) {
	ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
	for _, at := range ap {
		at.Execute()
	}
	cd := &CallDescriptor{
		Direction:    "*out",
		Category:     "call",
		Tenant:       "cgrates.org",
		Subject:      "dy",
		Account:      "dy",
		Destination:  "0723123113",
		TimeStart:    time.Date(2015, 10, 26, 13, 29, 27, 0, time.UTC),
		TimeEnd:      time.Date(2015, 10, 26, 13, 29, 51, 0, time.UTC),
		MaxCostSoFar: 0,
	}
	acc, err := accountingStorage.GetAccount("cgrates.org:dy")
	if err != nil || acc.BalanceMap[utils.MONETARY][0].Value != 1 {
		t.Errorf("Error getting account: %+v (%v)", utils.ToIJSON(acc), err)
	}
	cc, err := cd.MaxDebit()
	expected := 0.39
	if cc.Cost != expected || err != nil {
		t.Log(utils.ToIJSON(cc))
		t.Errorf("Expected %v was %+v", expected, cc)
	}
	acc, err = accountingStorage.GetAccount("cgrates.org:dy")
	if err != nil || acc.BalanceMap[utils.MONETARY][0].Value != 1-expected {
		t.Errorf("Error getting account: %+v (%v)", utils.ToIJSON(acc), err)
	}
}
示例#2
0
func TestTpZeroNegativeCost(t *testing.T) {
	if !*testIntegration {
		return
	}
	tStart := time.Date(2016, 3, 31, 0, 0, 0, 0, time.UTC)
	cd := engine.CallDescriptor{
		Direction:     "*out",
		Category:      "call",
		Tenant:        "cgrates.org",
		Subject:       "free",
		Account:       "1013",
		Destination:   "+4915",
		DurationIndex: 0,
		TimeStart:     tStart,
		TimeEnd:       tStart.Add(time.Duration(20) * time.Second),
	}
	var cc engine.CallCost
	if err := tpRPC.Call("Responder.Debit", cd, &cc); err != nil {
		t.Error("Got error on Responder.GetCost: ", err.Error())
	} else if cc.GetDuration() != 20*time.Second {
		t.Errorf("Calling Responder.MaxDebit got callcost: %v", utils.ToIJSON(cc))
	}
	var acnt engine.Account
	attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1013"}
	if err := tpRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil {
		t.Error("Got error on ApierV2.GetAccount: ", err.Error())
	} else if acnt.BalanceMap[utils.VOICE][0].Value != 100.0 {
		t.Errorf("Calling ApierV2.GetAccount received: %s", utils.ToIJSON(acnt))
	}
}
示例#3
0
func TestApierResetAccountActionTriggers(t *testing.T) {
	if !*testIntegration {
		return
	}
	var acnt engine.Account
	attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005"}
	if err := tpRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil {
		t.Error(err)
	} else if acnt.ActionTriggers[0].Executed == true {
		t.Errorf("wrong action trigger executed flag: %s", utils.ToIJSON(acnt.ActionTriggers))
	}
	var reply string
	if err := tpRPC.Call("ApierV2.ResetAccountActionTriggers", v1.AttrResetAccountActionTriggers{
		Tenant:   "cgrates.org",
		Account:  "1005",
		GroupID:  "STANDARD_TRIGGERS",
		Executed: true,
	}, &reply); err != nil {
		t.Error("Error on ApierV2.ResetAccountActionTriggers: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ApierV2.ResetAccountActionTriggers got reply: %s", reply)
	}
	if err := tpRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil {
		t.Error(err)
	} else if acnt.ActionTriggers[0].Executed == false {
		t.Errorf("wrong action trigger executed flag: %s", utils.ToIJSON(acnt.ActionTriggers))
	}
}
示例#4
0
func TestDestManagCacheWithGetCache(t *testing.T) {
	if !*testIntegration {
		return
	}
	if err := engine.InitDataDb(destCfg); err != nil {
		t.Fatal(err)
	}
	var reply string
	if err := destRPC.Call("ApierV1.ReloadCache", utils.AttrReloadCache{}, &reply); err != nil {
		t.Error("Got error on ApierV1.ReloadCache: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ApierV1.ReloadCache received: %+v", reply)
	}
	attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "test", "destinations", "cacheall"), FlushDb: true}
	if err := destRPC.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &destLoadInst); err != nil {
		t.Error(err)
	} else if destLoadInst.RatingLoadID == "" || destLoadInst.AccountingLoadID == "" {
		t.Error("Empty loadId received, loadInstance: ", destLoadInst)
	}
	time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups

	dests := make([]*engine.Destination, 0)
	if err := destRPC.Call("ApierV2.GetDestinations", v2.AttrGetDestinations{DestinationIDs: []string{}}, &dests); err != nil {
		t.Error("Got error on ApierV2.GetDestinations: ", err.Error())
	} else if len(dests) != 1 {
		t.Errorf("Calling ApierV2.GetDestinations got reply: %v", utils.ToIJSON(dests))
	}

	var rcvStats utils.CacheStats
	if err := destRPC.Call("ApierV1.GetCacheStats", utils.AttrCacheStats{}, &rcvStats); err != nil {
		t.Error("Got error on ApierV1.GetCacheStats: ", err.Error())
	} else if rcvStats.Destinations != 2 {
		t.Errorf("Calling ApierV1.GetCacheStats received: %+v", rcvStats)
	}

	attrs = &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "test", "destinations", "cacheone"), FlushDb: true}
	if err := destRPC.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &destLoadInst); err != nil {
		t.Error(err)
	} else if destLoadInst.RatingLoadID == "" || destLoadInst.AccountingLoadID == "" {
		t.Error("Empty loadId received, loadInstance: ", destLoadInst)
	}
	time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups

	dests = make([]*engine.Destination, 0)
	if err := destRPC.Call("ApierV2.GetDestinations", v2.AttrGetDestinations{DestinationIDs: []string{}}, &dests); err != nil {
		t.Error("Got error on ApierV2.GetDestinations: ", err.Error())
	} else if len(dests) != 1 {
		t.Errorf("Calling ApierV2.GetDestinations got reply: %v", utils.ToIJSON(dests))
	}

	if err := destRPC.Call("ApierV1.GetCacheStats", utils.AttrCacheStats{}, &rcvStats); err != nil {
		t.Error("Got error on ApierV1.GetCacheStats: ", err.Error())
	} else if rcvStats.Destinations != 1 {
		t.Errorf("Calling ApierV1.GetCacheStats received: %+v", rcvStats)
	}
}
示例#5
0
func TestRatingProfileYearMonthDay(t *testing.T) {
	ri := &RatingInfo{
		RateIntervals: RateIntervalList{
			&RateInterval{
				Timing: &RITiming{
					StartTime: "09:00:00",
				},
			},
			&RateInterval{
				Timing: &RITiming{
					StartTime: "00:00:00",
				},
			},
			&RateInterval{
				Timing: &RITiming{
					Years:     utils.Years{2016},
					Months:    utils.Months{1},
					MonthDays: utils.MonthDays{6, 7},
					WeekDays:  utils.WeekDays{},
					StartTime: "19:00:00",
				},
			},
		},
	}
	ts := &TimeSpan{
		TimeStart: time.Date(2016, 1, 6, 23, 40, 0, 0, time.UTC),
		TimeEnd:   time.Date(2016, 1, 7, 1, 1, 30, 0, time.UTC),
	}
	rIntervals := ri.SelectRatingIntevalsForTimespan(ts)
	if len(rIntervals) != 1 ||
		rIntervals[0].Timing.StartTime != "19:00:00" {
		t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals))
	}
}
示例#6
0
func TestRatingProfileRIforTSMidnight(t *testing.T) {
	ri := &RatingInfo{
		RateIntervals: RateIntervalList{
			&RateInterval{
				Timing: &RITiming{
					StartTime: "09:00:00",
				},
			},
			&RateInterval{
				Timing: &RITiming{
					StartTime: "00:00:00",
				},
			},
			&RateInterval{
				Timing: &RITiming{
					StartTime: "19:00:00",
				},
			},
		},
	}
	ts := &TimeSpan{
		TimeStart: time.Date(2016, 1, 6, 23, 40, 0, 0, time.UTC),
		TimeEnd:   time.Date(2016, 1, 7, 1, 1, 30, 0, time.UTC),
	}
	rIntervals := ri.SelectRatingIntevalsForTimespan(ts)
	if len(rIntervals) != 1 ||
		rIntervals[0].Timing.StartTime != "19:00:00" {
		t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals))
	}
}
示例#7
0
func TestTpActionTriggers(t *testing.T) {
	var atrs engine.ActionTriggers
	if err := tpRPC.Call("ApierV1.GetActionTriggers", v1.AttrGetActionTriggers{GroupIDs: []string{}}, &atrs); err != nil {
		t.Error("Got error on ApierV1.GetActionTriggers: ", err.Error())
	} else if len(atrs) != 9 {
		t.Errorf("Calling v1.GetActionTriggers got: %v", atrs)
	}
	var reply string
	if err := tpRPC.Call("ApierV1.SetActionTrigger", v1.AttrSetActionTrigger{
		GroupID:   "TestATR",
		UniqueID:  "Unique atr id",
		BalanceID: utils.StringPointer("BID1"),
	}, &reply); err != nil {
		t.Error("Got error on ApierV1.SetActionTrigger: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling v1.SetActionTrigger got: %v", reply)
	}

	if err := tpRPC.Call("ApierV1.GetActionTriggers", v1.AttrGetActionTriggers{GroupIDs: []string{}}, &atrs); err != nil {
		t.Error("Got error on ApierV1.GetActionTriggers: ", err.Error())
	} else if len(atrs) != 10 {
		t.Errorf("Calling v1.GetActionTriggers got: %v", atrs)
	}
	if err := tpRPC.Call("ApierV1.GetActionTriggers", v1.AttrGetActionTriggers{GroupIDs: []string{"TestATR"}}, &atrs); err != nil {
		t.Error("Got error on ApierV1.GetActionTriggers: ", err.Error())
	} else if len(atrs) != 1 {
		t.Errorf("Calling v1.GetActionTriggers got: %v", atrs)
	}
	if atrs[0].ID != "TestATR" ||
		atrs[0].UniqueID != "Unique atr id" ||
		*atrs[0].Balance.ID != "BID1" {
		t.Error("Wrong action trigger set: ", utils.ToIJSON(atrs[0]))
	}
}
示例#8
0
func TestDfGeneralJsonCfg(t *testing.T) {
	eCfg := &GeneralJsonCfg{
		Instance_id:          utils.StringPointer(""),
		Log_level:            utils.IntPointer(utils.LOGLEVEL_INFO),
		Http_skip_tls_verify: utils.BoolPointer(false),
		Rounding_decimals:    utils.IntPointer(5),
		Dbdata_encoding:      utils.StringPointer("msgpack"),
		Tpexport_dir:         utils.StringPointer("/var/spool/cgrates/tpe"),
		Httpposter_attempts:  utils.IntPointer(3),
		Http_failed_dir:      utils.StringPointer("/var/spool/cgrates/http_failed"),
		Default_request_type: utils.StringPointer(utils.META_RATED),
		Default_category:     utils.StringPointer("call"),
		Default_tenant:       utils.StringPointer("cgrates.org"),
		Default_timezone:     utils.StringPointer("Local"),
		Connect_attempts:     utils.IntPointer(3),
		Reconnects:           utils.IntPointer(-1),
		Connect_timeout:      utils.StringPointer("1s"),
		Reply_timeout:        utils.StringPointer("2s"),
		Response_cache_ttl:   utils.StringPointer("0s"),
		Internal_ttl:         utils.StringPointer("2m"),
		Locking_timeout:      utils.StringPointer("5s"),
	}
	if gCfg, err := dfCgrJsonCfg.GeneralJsonCfg(); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eCfg, gCfg) {
		t.Error("Received: ", utils.ToIJSON(gCfg))
	}
}
示例#9
0
func TestCacheJsonCfg(t *testing.T) {
	eCfg := &CacheJsonCfg{
		Destinations: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Reverse_destinations: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Rating_plans: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(true)},
		Rating_profiles: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Lcr: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Cdr_stats: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Actions: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Action_plans: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Action_triggers: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Shared_groups: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Aliases: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
		Reverse_aliases: &CacheParamJsonCfg{Limit: utils.IntPointer(10000),
			Ttl: utils.StringPointer("0s"), Precache: utils.BoolPointer(false)},
	}
	if gCfg, err := dfCgrJsonCfg.CacheJsonCfg(); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eCfg, gCfg) {
		t.Error("Received: ", utils.ToIJSON(gCfg))
	}
}
示例#10
0
func TestRatingProfileRISorter(t *testing.T) {
	ris := RateIntervalList{
		&RateInterval{
			Timing: &RITiming{
				StartTime: "09:00:00",
			},
		},
		&RateInterval{
			Timing: &RITiming{
				StartTime: "00:00:00",
			},
		},
		&RateInterval{
			Timing: &RITiming{
				StartTime: "19:00:00",
			},
		},
	}
	sorter := &RateIntervalTimeSorter{referenceTime: time.Date(2016, 1, 6, 19, 0, 0, 0, time.UTC), ris: ris}
	rIntervals := sorter.Sort()
	if len(rIntervals) != 3 ||
		rIntervals[0].Timing.StartTime != "00:00:00" ||
		rIntervals[1].Timing.StartTime != "09:00:00" ||
		rIntervals[2].Timing.StartTime != "19:00:00" {
		t.Error("Wrong interval list: ", utils.ToIJSON(rIntervals))
	}
}
示例#11
0
func TestTpRemoveActionsRefenced(t *testing.T) {
	if !*testIntegration {
		return
	}

	// no more reference check for sake of speed!

	actionsMap := make(map[string]engine.Actions)
	if err := tpRPC.Call("ApierV2.GetActions", v2.AttrGetActions{
		ActionIDs: []string{"TOPUP_VOICE"},
	}, &actionsMap); err != nil {
		t.Error("Got error on ApierV2.GetActions: ", err.Error())
	} else if len(actionsMap) != 1 {
		t.Errorf("Calling ApierV2.GetActions got reply: %s", utils.ToIJSON(actionsMap))
	}
	var reply string
	if err := tpRPC.Call("ApierV2.RemoveActions", v1.AttrRemoveActions{
		ActionIDs: []string{"TOPUP_VOICE"},
	}, &reply); err != nil {
		t.Error("Error on ApierV2.RemoveActions: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ApierV2.RemoveActions got reply: %s", reply)
	}
	if err := tpRPC.Call("ApierV2.GetActions", v2.AttrGetActions{
		ActionIDs: []string{"PAYMENT_2056bd2fe137082970f97102b64e42fd"},
	}, &actionsMap); err == nil {
		t.Error("no error on ApierV2.GetActions: ", err)
	}
}
示例#12
0
func TestTpBalanceCounter(t *testing.T) {
	tStart := time.Date(2016, 3, 31, 0, 0, 0, 0, time.UTC)
	cd := engine.CallDescriptor{
		Direction:     "*out",
		Category:      "call",
		Tenant:        "cgrates.org",
		Subject:       "1001",
		Destination:   "+49",
		DurationIndex: 0,
		TimeStart:     tStart,
		TimeEnd:       tStart.Add(time.Duration(20) * time.Second),
	}
	var cc engine.CallCost
	if err := tpRPC.Call("Responder.Debit", cd, &cc); err != nil {
		t.Error("Got error on Responder.GetCost: ", err.Error())
	} else if cc.GetDuration() != 20*time.Second {
		t.Errorf("Calling Responder.MaxDebit got callcost: %v", cc.GetDuration())
	}
	var acnt *engine.Account
	attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"}
	if err := tpRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil {
		t.Error("Got error on ApierV2.GetAccount: ", err.Error())
	} else if acnt.UnitCounters[utils.MONETARY][1].Counters[0].Value != 20.0 {
		t.Errorf("Calling ApierV2.GetBalance received: %s", utils.ToIJSON(acnt))
	}
}
示例#13
0
func TestMaxDebitRatingInfoOnZeroTime(t *testing.T) {
	ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
	for _, at := range ap {
		at.Execute()
	}
	cd := &CallDescriptor{
		Direction:    "*out",
		Category:     "call",
		Tenant:       "cgrates.org",
		Subject:      "dy",
		Account:      "dy",
		Destination:  "0723123113",
		TimeStart:    time.Date(2015, 10, 26, 13, 29, 27, 0, time.UTC),
		TimeEnd:      time.Date(2015, 10, 26, 13, 29, 27, 0, time.UTC),
		MaxCostSoFar: 0,
	}
	cc, err := cd.MaxDebit()
	if err != nil ||
		len(cc.Timespans) != 1 ||
		cc.Timespans[0].MatchedDestId != "RET" ||
		cc.Timespans[0].MatchedSubject != "*out:cgrates.org:call:dy" ||
		cc.Timespans[0].MatchedPrefix != "0723" ||
		cc.Timespans[0].RatingPlanId != "DY_PLAN" {
		t.Error("MatchedInfo not added:", utils.ToIJSON(cc))
	}
}
示例#14
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{Field_id: utils.StringPointer(utils.TOR), Value: utils.StringPointer("~7:s/^(voice|data|sms|mms|generic)$/*$1/")},
		&CdrFieldJsonCfg{Field_id: utils.StringPointer(utils.ANSWER_TIME), Value: utils.StringPointer("1")},
		&CdrFieldJsonCfg{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: ", utils.ToIJSON(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)
	}
}
示例#15
0
func TestLoadAccountActions(t *testing.T) {
	if len(csvr.accountActions) != 17 {
		t.Error("Failed to load account actions: ", len(csvr.accountActions))
	}
	aa := csvr.accountActions["vdf:minitsboy"]
	expected := &Account{
		ID: "vdf:minitsboy",
		UnitCounters: UnitCounters{
			utils.VOICE: []*UnitCounter{
				&UnitCounter{
					CounterType: "*event",
					Counters: CounterFilters{
						&CounterFilter{
							Value: 0,
							Filter: &BalanceFilter{
								ID:             utils.StringPointer("st0"),
								Type:           utils.StringPointer(utils.VOICE),
								Directions:     utils.StringMapPointer(utils.NewStringMap("*out")),
								DestinationIDs: utils.StringMapPointer(utils.NewStringMap("GERMANY_O2")),
								SharedGroups:   nil,
								Categories:     nil,
								TimingIDs:      nil,
							},
						},
					},
				},
			},
		},
		ActionTriggers: csvr.actionsTriggers["STANDARD_TRIGGER"],
	}
	// set propper uuid
	for i, atr := range aa.ActionTriggers {
		csvr.actionsTriggers["STANDARD_TRIGGER"][i].ID = atr.ID
	}
	for i, b := range aa.UnitCounters[utils.VOICE][0].Counters {
		expected.UnitCounters[utils.VOICE][0].Counters[i].Filter.ID = b.Filter.ID
	}
	if !reflect.DeepEqual(aa.UnitCounters[utils.VOICE][0].Counters[0], expected.UnitCounters[utils.VOICE][0].Counters[0]) {
		t.Errorf("Error loading account action: %+v", utils.ToIJSON(aa.UnitCounters[utils.VOICE][0].Counters[0].Filter))
	}
	// test that it does not overwrite balances
	existing, err := accountingStorage.GetAccount(aa.ID)
	if err != nil || len(existing.BalanceMap) != 2 {
		t.Errorf("The account was not set before load: %+v", existing)
	}
	accountingStorage.SetAccount(aa)
	existing, err = accountingStorage.GetAccount(aa.ID)
	if err != nil || len(existing.BalanceMap) != 2 {
		t.Errorf("The set account altered the balances: %+v", existing)
	}
}
示例#16
0
func TestTpCreateExecuteActionMatch(t *testing.T) {
	if !*testIntegration {
		return
	}
	var reply string
	if err := tpRPC.Call("ApierV2.SetActions", utils.AttrSetActions{
		ActionsId: "PAYMENT_2056bd2fe137082970f97102b64e42fd",
		Actions: []*utils.TPAction{
			&utils.TPAction{
				BalanceType:   "*monetary",
				Directions:    "*out",
				Identifier:    "*topup",
				RatingSubject: "",
				Units:         "10.500000",
				Weight:        10,
			},
		},
	}, &reply); err != nil {
		t.Error("Got error on ApierV2.SetActions: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ApierV2.SetActions got reply: %s", reply)
	}
	if err := tpRPC.Call("ApierV2.ExecuteAction", utils.AttrExecuteAction{
		Tenant:    "cgrates.org",
		Account:   "1015",
		ActionsId: "PAYMENT_2056bd2fe137082970f97102b64e42fd",
	}, &reply); err != nil {
		t.Error("Got error on ApierV2.ExecuteAction: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ExecuteAction got reply: %s", reply)
	}
	if err := tpRPC.Call("ApierV2.ExecuteAction", utils.AttrExecuteAction{
		Tenant:    "cgrates.org",
		Account:   "1015",
		ActionsId: "PAYMENT_2056bd2fe137082970f97102b64e42fd",
	}, &reply); err != nil {
		t.Error("Got error on ApierV2.ExecuteAction: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ExecuteAction got reply: %s", reply)
	}
	var acnt engine.Account
	attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1015"}
	if err := tpRPC.Call("ApierV2.GetAccount", attrs, &acnt); err != nil {
		t.Error("Got error on ApierV2.GetAccount: ", err.Error())
	}
	if len(acnt.BalanceMap) != 1 ||
		len(acnt.BalanceMap[utils.MONETARY]) != 1 ||
		acnt.BalanceMap[utils.MONETARY].GetTotalValue() != 21 {
		t.Error("error matching previous created balance: ", utils.ToIJSON(acnt.BalanceMap))
	}
}
示例#17
0
func TestLoadActionTriggers(t *testing.T) {
	if len(csvr.actionsTriggers) != 7 {
		t.Error("Failed to load action triggers: ", len(csvr.actionsTriggers))
	}
	atr := csvr.actionsTriggers["STANDARD_TRIGGER"][0]
	expected := &ActionTrigger{
		ID:             "STANDARD_TRIGGER",
		UniqueID:       "st0",
		ThresholdType:  utils.TRIGGER_MIN_EVENT_COUNTER,
		ThresholdValue: 10,
		Balance: &BalanceFilter{
			ID:             nil,
			Type:           utils.StringPointer(utils.VOICE),
			Directions:     utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
			DestinationIDs: utils.StringMapPointer(utils.NewStringMap("GERMANY_O2")),
			Categories:     nil,
			TimingIDs:      nil,
			SharedGroups:   nil,
			Disabled:       nil,
			Blocker:        nil,
		},
		Weight:    10,
		ActionsID: "SOME_1",
		Executed:  false,
	}
	if !reflect.DeepEqual(atr, expected) {
		t.Errorf("Error loading action trigger: %+v", utils.ToIJSON(atr.Balance))
	}
	atr = csvr.actionsTriggers["STANDARD_TRIGGER"][1]
	expected = &ActionTrigger{
		ID:             "STANDARD_TRIGGER",
		UniqueID:       "st1",
		ThresholdType:  utils.TRIGGER_MAX_BALANCE,
		ThresholdValue: 200,
		Balance: &BalanceFilter{
			Type:           utils.StringPointer(utils.VOICE),
			Directions:     utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
			DestinationIDs: utils.StringMapPointer(utils.NewStringMap("GERMANY")),
			Categories:     nil,
			TimingIDs:      nil,
			SharedGroups:   nil,
		},
		Weight:    10,
		ActionsID: "SOME_2",
		Executed:  false,
	}
	if !reflect.DeepEqual(atr, expected) {
		t.Errorf("Error loading action trigger: %+v", atr)
	}
}
示例#18
0
func TestResponderGetSessionRuns(t *testing.T) {
	testTenant := "vdf"
	cdr := &CDR{CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf",
		OriginHost: "192.168.1.1", Source: "test", RequestType: utils.META_PREPAID, Direction: "*out", Tenant: testTenant, Category: "call", Account: "dan2", Subject: "dan2",
		Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), PDD: 3 * time.Second,
		AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Supplier: "suppl1",
		RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second,
		ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01}
	keyCharger1 := utils.ConcatenatedKey("*out", testTenant, "call", "dan2", "dan2")
	dfDC := &utils.DerivedCharger{RunID: utils.DEFAULT_RUNID, RequestTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
		CategoryField: utils.META_DEFAULT, AccountField: utils.META_DEFAULT, SubjectField: utils.META_DEFAULT, DestinationField: utils.META_DEFAULT,
		SetupTimeField: utils.META_DEFAULT, PDDField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT,
		DisconnectCauseField: utils.META_DEFAULT, CostField: utils.META_DEFAULT, RatedField: utils.META_DEFAULT}
	extra1DC := &utils.DerivedCharger{RunID: "extra1", RequestTypeField: "^" + utils.META_PREPAID, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
		CategoryField: "^0", AccountField: "^minitsboy", SubjectField: "^rif", DestinationField: "^0256",
		SetupTimeField: utils.META_DEFAULT, PDDField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT}
	extra2DC := &utils.DerivedCharger{RunID: "extra2", RequestTypeField: utils.META_DEFAULT, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
		CategoryField: utils.META_DEFAULT, AccountField: "^ivo", SubjectField: "^ivo", DestinationField: utils.META_DEFAULT,
		SetupTimeField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT}
	extra3DC := &utils.DerivedCharger{RunID: "extra3", RequestTypeField: "^" + utils.META_PSEUDOPREPAID, DirectionField: utils.META_DEFAULT, TenantField: utils.META_DEFAULT,
		CategoryField: "^0", AccountField: "^minu", SubjectField: "^rif", DestinationField: "^0256",
		SetupTimeField: utils.META_DEFAULT, PDDField: utils.META_DEFAULT, AnswerTimeField: utils.META_DEFAULT, UsageField: utils.META_DEFAULT, SupplierField: utils.META_DEFAULT,
		DisconnectCauseField: utils.META_DEFAULT}
	charger1 := &utils.DerivedChargers{Chargers: []*utils.DerivedCharger{extra1DC, extra2DC, extra3DC}}
	if err := ratingStorage.SetDerivedChargers(keyCharger1, charger1); err != nil {
		t.Error("Error on setting DerivedChargers", err.Error())
	}
	ratingStorage.CacheRatingAll("TestResponderGetSessionRuns")
	sesRuns := make([]*SessionRun, 0)
	eSRuns := []*SessionRun{
		&SessionRun{DerivedCharger: extra1DC,
			CallDescriptor: &CallDescriptor{CgrID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), RunID: "extra1", Direction: "*out", Category: "0",
				Tenant: "vdf", Subject: "rif", Account: "minitsboy", Destination: "0256", TimeStart: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), TimeEnd: time.Date(2013, 11, 7, 8, 42, 36, 0, time.UTC), TOR: utils.VOICE, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}}},
		&SessionRun{DerivedCharger: extra2DC,
			CallDescriptor: &CallDescriptor{CgrID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), RunID: "extra2", Direction: "*out", Category: "call",
				Tenant: "vdf", Subject: "ivo", Account: "ivo", Destination: "1002", TimeStart: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), TimeEnd: time.Date(2013, 11, 7, 8, 42, 36, 0, time.UTC), TOR: utils.VOICE, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}}},
		&SessionRun{DerivedCharger: dfDC,
			CallDescriptor: &CallDescriptor{CgrID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), RunID: "*default", Direction: "*out", Category: "call",
				Tenant: "vdf", Subject: "dan2", Account: "dan2", Destination: "1002", TimeStart: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), TimeEnd: time.Date(2013, 11, 7, 8, 42, 36, 0, time.UTC), TOR: utils.VOICE, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}}}}
	if err := rsponder.GetSessionRuns(cdr, &sesRuns); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eSRuns, sesRuns) {
		for _, sr := range sesRuns {
			t.Logf("sr cd: %s", utils.ToIJSON(sr.CallDescriptor))
		}
		t.Errorf("Expecting: %+v, received: %+v", eSRuns, sesRuns)
	}
}
示例#19
0
func testSMCosts(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
	}
	cc := &CallCost{
		Direction:   utils.OUT,
		Destination: "+4986517174963",
		Timespans: []*TimeSpan{
			&TimeSpan{
				TimeStart:     time.Date(2015, 12, 28, 8, 53, 0, 0, time.UTC).Local(), // MongoDB saves timestamps in local timezone
				TimeEnd:       time.Date(2015, 12, 28, 8, 54, 40, 0, time.UTC).Local(),
				DurationIndex: 0,
				RateInterval:  &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 100, RateIncrement: 10 * time.Second, RateUnit: time.Second}}}},
			},
		},
		TOR: utils.VOICE,
	}
	if err := cdrStorage.SetSMCost(&SMCost{CGRID: "164b0422fdc6a5117031b427439482c6a4f90e41", RunID: utils.META_DEFAULT, OriginHost: "localhost", OriginID: "12345",
		CostSource: utils.UNIT_TEST, CostDetails: cc}); err != nil {
		return err
	}
	if rcvSMC, err := cdrStorage.GetSMCosts("164b0422fdc6a5117031b427439482c6a4f90e41", utils.META_DEFAULT, "", ""); err != nil {
		return err
	} else if len(rcvSMC) == 0 {
		return errors.New("No SMCosts received")
	} else if len(cc.Timespans) != len(rcvSMC[0].CostDetails.Timespans) { // cc.Timespans[0].RateInterval.Rating.Rates[0], rcvCC.Timespans[0].RateInterval.Rating.Rates[0])
		return fmt.Errorf("Expecting: %+v, received: %+s", cc, utils.ToIJSON(rcvSMC[0]))
	}
	// Test query per prefix
	for i := 0; i < 3; i++ {
		if err := cdrStorage.SetSMCost(&SMCost{CGRID: "164b0422fdc6a5117031b427439482c6a4f90e5" + strconv.Itoa(i), RunID: utils.META_DEFAULT, OriginHost: "localhost", OriginID: "abc" + strconv.Itoa(i),
			CostSource: utils.UNIT_TEST, CostDetails: cc}); err != nil {
			return err
		}
	}
	if rcvSMC, err := cdrStorage.GetSMCosts("", utils.META_DEFAULT, "localhost", "abc"); err != nil {
		return err
	} else if len(rcvSMC) != 3 {
		return fmt.Errorf("Expecting 3, received: %d", len(rcvSMC))
	}
	return nil
}
示例#20
0
func TestMaxSesionTimeLongerThanMoney(t *testing.T) {
	cd := &CallDescriptor{
		TimeStart:   time.Date(2015, 07, 24, 13, 37, 0, 0, time.UTC),
		TimeEnd:     time.Date(2015, 07, 24, 16, 37, 0, 0, time.UTC),
		Direction:   "*out",
		Category:    "call",
		Tenant:      "cgrates.org",
		Subject:     "money",
		Destination: "0723",
	}
	acc, _ := accountingStorage.GetAccount("cgrates.org:money")
	allowedTime, err := cd.getMaxSessionDuration(acc)
	expected, err := time.ParseDuration("9999s") // 1 is the connect fee
	if err != nil || allowedTime != expected {
		t.Log(utils.ToIJSON(acc))
		t.Errorf("Expected: %v got %v", expected, allowedTime)
	}
}
示例#21
0
func TestDestManagAllDestinationLoaded(t *testing.T) {
	if !*testIntegration {
		return
	}
	dests := make([]*engine.Destination, 0)
	if err := destRPC.Call("ApierV2.GetDestinations", v2.AttrGetDestinations{DestinationIDs: []string{}}, &dests); err != nil {
		t.Error("Got error on ApierV2.GetDestinations: ", err.Error())
	} else if len(dests) != 6 {
		t.Errorf("Calling ApierV2.GetDestinations got reply: %v", utils.ToIJSON(dests))
	}

	var rcvStats utils.CacheStats
	if err := destRPC.Call("ApierV1.GetCacheStats", utils.AttrCacheStats{}, &rcvStats); err != nil {
		t.Error("Got error on ApierV1.GetCacheStats: ", err.Error())
	} else if rcvStats.Destinations != 9 {
		t.Errorf("Calling ApierV1.GetCacheStats received: %+v", rcvStats)
	}
}
示例#22
0
func TestTpSetRemoveActions(t *testing.T) {
	if !*testIntegration {
		return
	}
	var reply string
	if err := tpRPC.Call("ApierV2.SetActions", utils.AttrSetActions{
		ActionsId: "TO_BE_DELETED",
		Actions: []*utils.TPAction{
			&utils.TPAction{
				BalanceType:   "*monetary",
				Directions:    "*out",
				Identifier:    "*topup",
				RatingSubject: "",
				Units:         "10.500000",
				Weight:        10,
			},
		},
	}, &reply); err != nil {
		t.Error("Got error on ApierV2.SetActions: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ApierV2.SetActions got reply: %s", reply)
	}
	actionsMap := make(map[string]engine.Actions)
	if err := tpRPC.Call("ApierV2.GetActions", v2.AttrGetActions{
		ActionIDs: []string{"PAYMENT_2056bd2fe137082970f97102b64e42fd"},
	}, &actionsMap); err != nil {
		t.Error("Got error on ApierV2.GetActions: ", err.Error())
	} else if len(actionsMap) != 1 {
		t.Errorf("Calling ApierV2.GetActions got reply: %s", utils.ToIJSON(actionsMap))
	}
	if err := tpRPC.Call("ApierV2.RemoveActions", v1.AttrRemoveActions{
		ActionIDs: []string{"PAYMENT_2056bd2fe137082970f97102b64e42fd"},
	}, &reply); err != nil {
		t.Error("Got error on ApierV2.RemoveActions: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ApierV2.RemoveActions got reply: %s", reply)
	}
	if err := tpRPC.Call("ApierV2.GetActions", v2.AttrGetActions{
		ActionIDs: []string{"PAYMENT_2056bd2fe137082970f97102b64e42fd"},
	}, &actionsMap); err == nil {
		t.Error("no error on ApierV2.GetActions: ", err)
	}
}
示例#23
0
func TestGetCostRoundingIssue(t *testing.T) {
	ap, _ := ratingStorage.GetActionPlans("TOPUP10_AT", false)
	for _, at := range ap {
		at.Execute()
	}
	cd := &CallDescriptor{
		Direction:    "*out",
		Category:     "call",
		Tenant:       "cgrates.org",
		Subject:      "dy",
		Account:      "dy",
		Destination:  "0723123113",
		TimeStart:    time.Date(2015, 10, 26, 13, 29, 27, 0, time.UTC),
		TimeEnd:      time.Date(2015, 10, 26, 13, 29, 51, 0, time.UTC),
		MaxCostSoFar: 0,
	}
	cc, err := cd.GetCost()
	expected := 0.17
	if cc.Cost != expected || err != nil {
		t.Log(utils.ToIJSON(cc))
		t.Errorf("Expected %v was %+v", expected, cc)
	}
}
示例#24
0
func TestStatsAppendCdr(t *testing.T) {
	cdrStats := NewStats(ratingStorage, accountingStorage, 0)
	cdr := &CDR{
		Tenant:          "cgrates.org",
		Category:        "call",
		AnswerTime:      time.Now(),
		SetupTime:       time.Now(),
		Usage:           10 * time.Second,
		Cost:            10,
		Supplier:        "suppl1",
		DisconnectCause: "NORMAL_CLEARNING",
	}
	err := cdrStats.AppendCDR(cdr, nil)
	if err != nil {
		t.Error("Error appending cdr to stats: ", err)
	}
	t.Log(cdrStats.queues)
	if len(cdrStats.queues) != 5 ||
		len(cdrStats.queues["CDRST1"].Cdrs) != 0 ||
		len(cdrStats.queues["CDRST2"].Cdrs) != 1 {
		t.Error("Error appending cdr to queue: ", utils.ToIJSON(cdrStats.queues))
	}
}
示例#25
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))
	}
}
示例#26
0
func TestLoadRatingPlans(t *testing.T) {
	if len(csvr.ratingPlans) != 14 {
		t.Error("Failed to load rating plans: ", len(csvr.ratingPlans))
	}
	rplan := csvr.ratingPlans["STANDARD"]
	expected := &RatingPlan{
		Id: "STANDARD",
		Timings: map[string]*RITiming{
			"59a981b9": &RITiming{
				Years:     utils.Years{},
				Months:    utils.Months{},
				MonthDays: utils.MonthDays{},
				WeekDays:  utils.WeekDays{1, 2, 3, 4, 5},
				StartTime: "00:00:00",
				tag:       "WORKDAYS_00",
			},
			"2d9ca6c4": &RITiming{
				Years:     utils.Years{},
				Months:    utils.Months{},
				MonthDays: utils.MonthDays{},
				WeekDays:  utils.WeekDays{1, 2, 3, 4, 5},
				StartTime: "18:00:00",
				tag:       "WORKDAYS_18",
			},
			"ec8ed374": &RITiming{
				Years:     utils.Years{},
				Months:    utils.Months{},
				MonthDays: utils.MonthDays{},
				WeekDays:  utils.WeekDays{time.Saturday, time.Sunday},
				StartTime: "00:00:00",
				tag:       "WEEKENDS",
			},
			"83429156": &RITiming{
				Years:     utils.Years{},
				Months:    utils.Months{},
				MonthDays: utils.MonthDays{},
				WeekDays:  utils.WeekDays{},
				StartTime: "00:00:00",
				tag:       "*any",
			},
		},
		Ratings: map[string]*RIRate{
			"ebefae11": &RIRate{
				ConnectFee: 0,
				Rates: []*Rate{
					&Rate{
						GroupIntervalStart: 0,
						Value:              0.2,
						RateIncrement:      time.Second,
						RateUnit:           time.Minute,
					},
				},
				RoundingMethod:   utils.ROUNDING_MIDDLE,
				RoundingDecimals: 4,
				tag:              "R1",
			},
			"fac0138e": &RIRate{
				ConnectFee: 0,
				Rates: []*Rate{
					&Rate{
						GroupIntervalStart: 0,
						Value:              0.1,
						RateIncrement:      time.Second,
						RateUnit:           time.Minute,
					},
				},
				RoundingMethod:   utils.ROUNDING_MIDDLE,
				RoundingDecimals: 4,
				tag:              "R2",
			},
			"781bfa03": &RIRate{
				ConnectFee: 0,
				Rates: []*Rate{
					&Rate{
						GroupIntervalStart: 0,
						Value:              0.05,
						RateIncrement:      time.Second,
						RateUnit:           time.Minute,
					},
				},
				RoundingMethod:   utils.ROUNDING_MIDDLE,
				RoundingDecimals: 4,
				tag:              "R3",
			},
			"f692daa4": &RIRate{
				ConnectFee: 0,
				Rates: []*Rate{
					&Rate{
						GroupIntervalStart: 0,
						Value:              0,
						RateIncrement:      time.Second,
						RateUnit:           time.Second,
					},
				},
				RoundingMethod:   utils.ROUNDING_MIDDLE,
				RoundingDecimals: 4,
				tag:              "R_URG",
			},
		},
		DestinationRates: map[string]RPRateList{
			"GERMANY": []*RPRate{
				&RPRate{
					Timing: "ec8ed374",
					Rating: "ebefae11",
					Weight: 10,
				},
				&RPRate{
					Timing: "83429156",
					Rating: "fac0138e",
					Weight: 10,
				},
				&RPRate{
					Timing: "a60bfb13",
					Rating: "fac0138e",
					Weight: 10,
				},
			},
			"GERMANY_O2": []*RPRate{
				&RPRate{
					Timing: "ec8ed374",
					Rating: "fac0138e",
					Weight: 10,
				},
				&RPRate{
					Timing: "83429156",
					Rating: "781bfa03",
					Weight: 10,
				},
				&RPRate{
					Timing: "a60bfb13",
					Rating: "781bfa03",
					Weight: 10,
				},
			},
			"GERMANY_PREMIUM": []*RPRate{
				&RPRate{
					Timing: "ec8ed374",
					Rating: "16e9ee19",
					Weight: 10,
				},
			},
			"URG": []*RPRate{
				&RPRate{
					Timing: "2d9ca64",
					Rating: "f692daa4",
					Weight: 20,
				},
			},
		},
	}
	if !reflect.DeepEqual(rplan.Ratings, expected.Ratings) {
		/*for tag, key := range rplan.Ratings {
			log.Print(tag, key)
		}*/
		t.Errorf("Expecting: %s, received: %s", utils.ToIJSON(expected.Ratings), utils.ToIJSON(rplan.Ratings))
	}
	anyTiming := &RITiming{
		Years:      utils.Years{},
		Months:     utils.Months{},
		MonthDays:  utils.MonthDays{},
		WeekDays:   utils.WeekDays{},
		StartTime:  "00:00:00",
		EndTime:    "",
		cronString: "",
		tag:        utils.ANY,
	}

	if !reflect.DeepEqual(csvr.ratingPlans["ANY_PLAN"].Timings["1323e132"], anyTiming) {
		t.Errorf("Error using *any timing in rating plans: %+v : %+v", csvr.ratingPlans["ANY_PLAN"].Timings["1323e132"], anyTiming)
	}
}
示例#27
0
func TestLoadActions(t *testing.T) {
	if len(csvr.actions) != 16 {
		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)
	}
	asGnrc := csvr.actions["TOPUP_RST_GNR_1000"]
	//TOPUP_RST_GNR_1000,*topup_reset,"{""*voice"": 60.0,""*data"":1024.0,""*sms"":1.0}",,,*generic,*out,,*any,,,*unlimited,,1000,20,false,false,10
	expected = []*Action{
		&Action{
			Id:               "TOPUP_RST_GNR_1000",
			ActionType:       TOPUP_RESET,
			ExtraParameters:  `{"*voice": 60.0,"*data":1024.0,"*sms":1.0}`,
			Weight:           10,
			ExpirationString: utils.UNLIMITED,
			Balance: &BalanceFilter{
				Uuid:       asGnrc[0].Balance.Uuid,
				Type:       utils.StringPointer(utils.GENERIC),
				Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)),
				//DestinationIDs: utils.StringMapPointer(utils.NewStringMap("*any")),
				Value:    &utils.ValueFormula{Static: 1000},
				Weight:   utils.Float64Pointer(20),
				Disabled: utils.BoolPointer(false),
				Blocker:  utils.BoolPointer(false),
			},
		},
	}
	if !reflect.DeepEqual(asGnrc, expected) {
		t.Errorf("Expecting: %+v, received: %+v", expected[0].Balance, asGnrc[0].Balance)
	}
}
示例#28
0
func TestDestManagCacheWithGetCost(t *testing.T) {
	if !*testIntegration {
		return
	}
	if err := engine.InitDataDb(destCfg); err != nil {
		t.Fatal(err)
	}
	var reply string
	if err := destRPC.Call("ApierV1.ReloadCache", utils.AttrReloadCache{}, &reply); err != nil {
		t.Error("Got error on ApierV1.ReloadCache: ", err.Error())
	} else if reply != utils.OK {
		t.Errorf("Calling ApierV1.ReloadCache received: %+v", reply)
	}
	attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "test", "destinations", "cacheall"), FlushDb: true}
	if err := destRPC.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &destLoadInst); err != nil {
		t.Error(err)
	} else if destLoadInst.RatingLoadID == "" || destLoadInst.AccountingLoadID == "" {
		t.Error("Empty loadId received, loadInstance: ", destLoadInst)
	}
	time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups

	dests := make([]*engine.Destination, 0)
	if err := destRPC.Call("ApierV2.GetDestinations", v2.AttrGetDestinations{DestinationIDs: []string{}}, &dests); err != nil {
		t.Error("Got error on ApierV2.GetDestinations: ", err.Error())
	} else if len(dests) != 1 {
		t.Errorf("Calling ApierV2.GetDestinations got reply: %v", utils.ToIJSON(dests))
	}

	var cc engine.CallCost
	cd := &engine.CallDescriptor{
		Direction:   "*out",
		Tenant:      "cgrates.org",
		Category:    "call",
		Account:     "test",
		Destination: "1002",
		TimeStart:   time.Date(2016, 2, 24, 0, 0, 0, 0, time.UTC),
		TimeEnd:     time.Date(2016, 2, 24, 0, 0, 10, 0, time.UTC),
	}
	if err := destRPC.Call("Responder.GetCost", cd, &cc); err != nil {
		t.Error(err)
	} else if cc.Cost != 1.6667 {
		t.Error("Empty loadId received, loadInstance: ", utils.ToIJSON(cc))
	}

	attrs = &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "test", "destinations", "cacheone"), FlushDb: true}
	if err := destRPC.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &destLoadInst); err != nil {
		t.Error(err)
	} else if destLoadInst.RatingLoadID == "" || destLoadInst.AccountingLoadID == "" {
		t.Error("Empty loadId received, loadInstance: ", destLoadInst)
	}
	time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups

	dests = make([]*engine.Destination, 0)
	if err := destRPC.Call("ApierV2.GetDestinations", v2.AttrGetDestinations{DestinationIDs: []string{}}, &dests); err != nil {
		t.Error("Got error on ApierV2.GetDestinations: ", err.Error())
	} else if len(dests) != 1 {
		t.Errorf("Calling ApierV2.GetDestinations got reply: %v", utils.ToIJSON(dests))
	}

	if err := destRPC.Call("Responder.GetCost", cd, &cc); err.Error() != utils.ErrUnauthorizedDestination.Error() {
		t.Error(err)
	}
}
示例#29
0
文件: lcr_test.go 项目: iwada/cgrates
func TestLCRCostSuppliersLoadAllOverMisingParams(t *testing.T) {
	setupTime := time.Date(2015, 7, 31, 6, 43, 0, 0, time.UTC)
	lcrCost := &LCRCost{
		Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", Strategy: LCR_STRATEGY_LOAD, StrategyParams: "", Weight: 10.0},
		SupplierCosts: []*LCRSupplierCost{
			&LCRSupplierCost{
				Supplier: "*out:tenant12:call:ivo12",
				supplierQueues: []*StatsQueue{
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{SetupTime: setupTime}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  3 * time.Minute,
						},
					},
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  1 * time.Minute,
						},
					},
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  10 * time.Minute,
						},
					},
				},
			},
			&LCRSupplierCost{
				Supplier: "*out:tenant12:call:dan12",
				supplierQueues: []*StatsQueue{
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{SetupTime: setupTime.Add(60 * time.Minute)}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  10 * time.Minute,
						},
					},
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{SetupTime: setupTime}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  7 * time.Minute,
						},
					},
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{SetupTime: setupTime}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  7 * time.Minute,
						},
					},
				},
			},
			&LCRSupplierCost{
				Supplier: "*out:tenant12:call:rif12",
				supplierQueues: []*StatsQueue{
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{}, &QCdr{SetupTime: setupTime}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  7 * time.Minute,
						},
					},
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{}, &QCdr{SetupTime: setupTime}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  7 * time.Minute,
						},
					},
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{SetupTime: setupTime.Add(200 * time.Minute)}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  10 * time.Minute,
						},
					},
					&StatsQueue{
						Cdrs: []*QCdr{&QCdr{}, &QCdr{SetupTime: setupTime}},
						conf: &CdrStats{
							QueueLength: 0,
							TimeWindow:  1 * time.Minute,
						},
					},
				},
			},
		},
	}
	lcrCost.Sort()
	if len(lcrCost.SupplierCosts) != 3 {
		t.Error("Error soring on load distribution: ", utils.ToIJSON(lcrCost))
	}
}
示例#30
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)
	}
}