timings and rate groups validation

This commit is contained in:
Radu Ioan Fericean
2015-05-21 15:41:05 +03:00
parent 3a0fe8e67c
commit bb6a7ea6c3
5 changed files with 143 additions and 35 deletions

View File

@@ -162,12 +162,8 @@ func (csvr *CSVReader) LoadRates() (err error) {
return err
}
// same tag only to create rate groups
existingRates, exists := csvr.tp.rates[tag]
_, exists := csvr.tp.rates[tag]
if exists {
rss := existingRates.RateSlots
if err := ValidNextGroup(rss[len(rss)-1], r.RateSlots[0]); err != nil {
return fmt.Errorf("RatesTag: %s, error: <%s>", tag, err.Error())
}
csvr.tp.rates[tag].RateSlots = append(csvr.tp.rates[tag].RateSlots, r.RateSlots[0])
} else {
csvr.tp.rates[tag] = r

View File

@@ -23,7 +23,6 @@ import (
"errors"
"fmt"
"log"
"math"
"os"
"path"
"regexp"
@@ -170,10 +169,18 @@ func NewTPData() *TPData {
func (tp *TPData) IsValid() bool {
valid := true
for rplTag, rpl := range tp.ratingPlans {
if !rpl.IsValid() {
if !rpl.isContinous() {
log.Printf("The rating plan %s is not covering all weekdays", rplTag)
valid = false
}
if !rpl.areRatesSane() {
log.Printf("The rating plan %s contains invalid rate groups", rplTag)
valid = false
}
if !rpl.areTimingsSane() {
log.Printf("The rating plan %s contains invalid timings", rplTag)
valid = false
}
}
return valid
}
@@ -507,16 +514,6 @@ func NewLoadRate(tag, connectFee, price, ratedUnits, rateIncrements, groupInterv
return
}
func ValidNextGroup(present, next *utils.RateSlot) error {
if next.GroupIntervalStartDuration() <= present.GroupIntervalStartDuration() {
return errors.New(fmt.Sprintf("Next rate group interval start: %#v must be heigher than the previous one: %#v", next, present))
}
if math.Mod(next.GroupIntervalStartDuration().Seconds(), present.RateIncrementDuration().Seconds()) != 0 {
return errors.New(fmt.Sprintf("GroupIntervalStart of %#v must be a multiple of RateIncrement of %#v", next, present))
}
return nil
}
func NewTiming(timingInfo ...string) (rt *utils.TPTiming) {
rt = &utils.TPTiming{}
rt.Id = timingInfo[0]

View File

@@ -20,6 +20,7 @@ package engine
import (
"encoding/json"
"math"
"github.com/cgrates/cgrates/history"
)
@@ -114,7 +115,7 @@ func (rp *RatingPlan) GetHistoryRecord() history.Record {
}
// IsValid determines if the rating plan covers a continous period of time
func (rp *RatingPlan) IsValid() bool {
func (rp *RatingPlan) isContinous() bool {
weekdays := make([]int, 7)
for _, tm := range rp.Timings {
// if it is a blank timing than it will match all
@@ -146,3 +147,31 @@ func (rp *RatingPlan) IsValid() bool {
}
return false
}
func (rp *RatingPlan) areRatesSane() bool {
for _, rating := range rp.Ratings {
rating.Rates.Sort()
for i, rate := range rating.Rates {
if i < (len(rating.Rates) - 1) {
nextRate := rating.Rates[i+1]
if nextRate.GroupIntervalStart <= rate.GroupIntervalStart {
return false
}
if math.Mod(nextRate.GroupIntervalStart.Seconds(), rate.RateIncrement.Seconds()) != 0 {
return false
}
}
}
}
return true
}
func (rp *RatingPlan) areTimingsSane() bool {
for _, timing := range rp.Timings {
if (len(timing.Years) != 0 || len(timing.Months) != 0 || len(timing.MonthDays) != 0) &&
len(timing.WeekDays) != 0 {
return false
}
}
return true
}

View File

@@ -218,26 +218,26 @@ func TestGetActiveForCall(t *testing.T) {
}
}
func TestRatingPlanIsValidEmpty(t *testing.T) {
func TestRatingPlanIsContinousEmpty(t *testing.T) {
rpl := &RatingPlan{}
if rpl.IsValid() {
if rpl.isContinous() {
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
}
}
func TestRatingPlanIsValidBlank(t *testing.T) {
func TestRatingPlanIsContinousBlank(t *testing.T) {
rpl := &RatingPlan{
Timings: map[string]*RITiming{
"blank": &RITiming{StartTime: "00:00:00"},
"other": &RITiming{WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"},
},
}
if !rpl.IsValid() {
if !rpl.isContinous() {
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
}
}
func TestRatingPlanIsValidGood(t *testing.T) {
func TestRatingPlanIsContinousGood(t *testing.T) {
rpl := &RatingPlan{
Timings: map[string]*RITiming{
"first": &RITiming{WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"},
@@ -245,24 +245,24 @@ func TestRatingPlanIsValidGood(t *testing.T) {
"third": &RITiming{WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"},
},
}
if !rpl.IsValid() {
if !rpl.isContinous() {
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
}
}
func TestRatingPlanIsValidBad(t *testing.T) {
func TestRatingPlanisContinousBad(t *testing.T) {
rpl := &RatingPlan{
Timings: map[string]*RITiming{
"first": &RITiming{WeekDays: utils.WeekDays{1, 2, 3}, StartTime: "00:00:00"},
"second": &RITiming{WeekDays: utils.WeekDays{4, 5, 0}, StartTime: "00:00:00"},
},
}
if rpl.IsValid() {
if rpl.isContinous() {
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
}
}
func TestRatingPlanIsValidSpecial(t *testing.T) {
func TestRatingPlanIsContinousSpecial(t *testing.T) {
rpl := &RatingPlan{
Timings: map[string]*RITiming{
"special": &RITiming{Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"},
@@ -271,12 +271,12 @@ func TestRatingPlanIsValidSpecial(t *testing.T) {
"third": &RITiming{WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"},
},
}
if !rpl.IsValid() {
if !rpl.isContinous() {
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
}
}
func TestRatingPlanIsValidMultiple(t *testing.T) {
func TestRatingPlanIsContinousMultiple(t *testing.T) {
rpl := &RatingPlan{
Timings: map[string]*RITiming{
"special": &RITiming{Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"},
@@ -286,12 +286,12 @@ func TestRatingPlanIsValidMultiple(t *testing.T) {
"third": &RITiming{WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"},
},
}
if !rpl.IsValid() {
if !rpl.isContinous() {
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
}
}
func TestRatingPlanIsValidMissing(t *testing.T) {
func TestRatingPlanIsContinousMissing(t *testing.T) {
rpl := &RatingPlan{
Timings: map[string]*RITiming{
"special": &RITiming{Years: utils.Years{2015}, Months: utils.Months{5}, MonthDays: utils.MonthDays{1}, StartTime: "00:00:00"},
@@ -300,11 +300,100 @@ func TestRatingPlanIsValidMissing(t *testing.T) {
"third": &RITiming{WeekDays: utils.WeekDays{0}, StartTime: "00:00:00"},
},
}
if rpl.IsValid() {
if rpl.isContinous() {
t.Errorf("Error determining rating plan's valididty: %+v", rpl)
}
}
func TestRatingPlanSaneTimingsBad(t *testing.T) {
rpl := &RatingPlan{
Timings: map[string]*RITiming{
"one": &RITiming{Years: utils.Years{2015}, WeekDays: utils.WeekDays{time.Monday}},
},
}
if rpl.areTimingsSane() {
t.Errorf("Error detecting bad timings in rating profile: %+v", rpl)
}
}
func TestRatingPlanSaneTimingsGood(t *testing.T) {
rpl := &RatingPlan{
Timings: map[string]*RITiming{
"one": &RITiming{Years: utils.Years{2015}},
"two": &RITiming{WeekDays: utils.WeekDays{0, 1, 2, 3, 4}, StartTime: "00:00:00"},
},
}
if !rpl.areTimingsSane() {
t.Errorf("Error detecting bad timings in rating profile: %+v", rpl)
}
}
func TestRatingPlanSaneRatingsEqual(t *testing.T) {
rpl := &RatingPlan{
Ratings: map[string]*RIRate{
"one": &RIRate{
Rates: RateGroups{
&Rate{
GroupIntervalStart: 0 * time.Second,
RateIncrement: 30 * time.Second,
},
&Rate{
GroupIntervalStart: 0 * time.Second,
RateIncrement: 30 * time.Second,
},
},
},
},
}
if rpl.areRatesSane() {
t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl)
}
}
func TestRatingPlanSaneRatingsNotMultiple(t *testing.T) {
rpl := &RatingPlan{
Ratings: map[string]*RIRate{
"one": &RIRate{
Rates: RateGroups{
&Rate{
GroupIntervalStart: 0 * time.Second,
RateIncrement: 30 * time.Second,
},
&Rate{
GroupIntervalStart: 15 * time.Second,
RateIncrement: 30 * time.Second,
},
},
},
},
}
if rpl.areRatesSane() {
t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl)
}
}
func TestRatingPlanSaneRatingsGoot(t *testing.T) {
rpl := &RatingPlan{
Ratings: map[string]*RIRate{
"one": &RIRate{
Rates: RateGroups{
&Rate{
GroupIntervalStart: 60 * time.Second,
RateIncrement: 30 * time.Second,
},
&Rate{
GroupIntervalStart: 0 * time.Second,
RateIncrement: 30 * time.Second,
},
},
},
},
}
if !rpl.areRatesSane() {
t.Errorf("Error detecting bad rate groups in rating profile: %+v", rpl)
}
}
/**************************** Benchmarks *************************************/
func BenchmarkRatingPlanMarshalJson(b *testing.B) {

View File

@@ -1234,9 +1234,6 @@ func (self *SQLStorage) GetTpRates(tpid, tag string) (map[string]*utils.TPRate,
// same tag only to create rate groups
er, exists := rts[tr.Tag]
if exists {
if err := ValidNextGroup(er.RateSlots[len(er.RateSlots)-1], r.RateSlots[0]); err != nil {
return nil, err
}
er.RateSlots = append(er.RateSlots, r.RateSlots[0])
} else {
rts[tr.Tag] = r