Merge pull request #2261 from Trial97/v0.10

Updated RSRParser to not split the string between grave accent for v0.10
This commit is contained in:
Dan Christian Bogos
2020-07-03 11:50:18 +02:00
committed by GitHub
13 changed files with 242 additions and 221 deletions

View File

@@ -280,16 +280,16 @@ func testV1CDRsRefundOutOfSessionCost(t *testing.T) {
Usage: utils.DurationPointer(time.Duration(3 * time.Minute)),
Cost: utils.Float64Pointer(2.3),
Charges: []*engine.ChargingInterval{
&engine.ChargingInterval{
{
RatingID: "c1a5ab9",
Increments: []*engine.ChargingIncrement{
&engine.ChargingIncrement{
{
Usage: time.Duration(2 * time.Minute),
Cost: 2.0,
AccountingID: "a012888",
CompressFactor: 1,
},
&engine.ChargingIncrement{
{
Usage: time.Duration(1 * time.Second),
Cost: 0.005,
AccountingID: "44d6c02",
@@ -303,7 +303,7 @@ func testV1CDRsRefundOutOfSessionCost(t *testing.T) {
Tenant: "cgrates.org",
ID: "testV1CDRsRefundOutOfSessionCost",
BalanceSummaries: []*engine.BalanceSummary{
&engine.BalanceSummary{
{
UUID: balanceUuid,
Type: utils.MONETARY,
Value: 50,
@@ -364,7 +364,7 @@ func testV1CDRsRefundOutOfSessionCost(t *testing.T) {
utils.Account: "testV1CDRsRefundOutOfSessionCost",
utils.Destination: "+4986517174963",
utils.AnswerTime: time.Date(2019, 11, 27, 12, 21, 26, 0, time.UTC),
utils.Usage: time.Duration(123) * time.Minute,
utils.Usage: 123 * time.Minute,
},
},
}

View File

@@ -149,6 +149,7 @@ func testConfigSReloadConfigFromJSONSessionS(t *testing.T) {
"MinCallDuration": 0.,
"SessionTTL": 0.,
"SessionTTLLastUsed": nil,
"SessionTTLLastUsage": nil,
"SessionTTLMaxDelay": nil,
"SessionTTLUsage": nil,
"StoreSCosts": false,
@@ -166,7 +167,7 @@ func testConfigSReloadConfigFromJSONSessionS(t *testing.T) {
}, &rpl); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(exp, rpl) {
t.Errorf("Expected %+v , received: %+v ", exp, rpl)
t.Errorf("Expected %+v , received: %+v ", utils.ToJSON(exp), utils.ToJSON(rpl))
}
}

View File

@@ -94,9 +94,8 @@ func (dbcfg *DataDbCfg) loadFromJsonCfg(jsnDbCfg *DbJsonCfg) (err error) {
// if we have the connection internal we change the name so we can have internal rpc for each subsystem
if rplConn == utils.MetaInternal {
return fmt.Errorf("Replication connection ID needs to be different than *internal")
} else {
dbcfg.RplConns[idx] = rplConn
}
dbcfg.RplConns[idx] = rplConn
}
}
if jsnDbCfg.Items != nil {

View File

@@ -35,6 +35,52 @@ func NewRSRParsers(parsersRules string, allFiltersMatch bool, rsrSeparator strin
if parsersRules == "" {
return
}
if count := strings.Count(parsersRules, "`"); count%2 != 0 { // check if we have matching `
return nil, fmt.Errorf("Unclosed unspilit syntax")
} else if count != 0 {
var splitedRule []string
for idx := strings.IndexByte(parsersRules, '`'); idx != -1; idx = strings.IndexByte(parsersRules, '`') {
insideARulePrefix := !strings.HasSuffix(parsersRules[:idx], utils.INFIELD_SEP) // if doesn't have ; we need to concatenate it with last rule
if insideARulePrefix {
splitedRule = append(splitedRule, strings.Split(parsersRules[:idx], utils.INFIELD_SEP)...)
} else {
splitedRule = append(splitedRule, strings.Split(parsersRules[:idx-1], utils.INFIELD_SEP)...)
}
parsersRules = parsersRules[idx+1:]
idx = strings.IndexByte(parsersRules, '`')
if insideARulePrefix {
splitedRule[len(splitedRule)-1] += parsersRules[:idx]
} else {
splitedRule = append(splitedRule, parsersRules[:idx])
}
parsersRules = parsersRules[idx+1:]
count -= 2 // the number of ` remaining
if len(parsersRules) == 0 {
continue
}
insideARuleSufix := !strings.HasPrefix(parsersRules, utils.INFIELD_SEP) // if doesn't have ; we need to concatenate it with last rule
if insideARuleSufix {
idx = strings.IndexByte(parsersRules, ';')
if idx == -1 {
idx = len(parsersRules)
splitedRule[len(splitedRule)-1] += parsersRules[:idx]
break
}
splitedRule[len(splitedRule)-1] += parsersRules[:idx]
} else {
idx = 0
}
parsersRules = parsersRules[idx+1:]
if len(parsersRules) == 0 {
break
}
if count == 0 { // no more ` so add the rest
splitedRule = append(splitedRule, strings.Split(parsersRules, utils.INFIELD_SEP)...)
break
}
}
return NewRSRParsersFromSlice(splitedRule, allFiltersMatch)
}
return NewRSRParsersFromSlice(strings.Split(parsersRules, rsrSeparator), allFiltersMatch)
}
@@ -95,18 +141,6 @@ func (prsrs RSRParsers) ParseValue(value interface{}) (out string, err error) {
return
}
// ParseEvent will parse the event values into one output
func (prsrs RSRParsers) ParseEvent(ev map[string]interface{}) (out string, err error) {
for _, prsr := range prsrs {
if outPrsr, err := prsr.ParseEvent(ev); err != nil {
return "", err
} else {
out += outPrsr
}
}
return
}
func (prsrs RSRParsers) ParseDataProvider(dP utils.DataProvider, separator string) (out string, err error) {
for _, prsr := range prsrs {
if outPrsr, err := prsr.ParseDataProvider(dP, separator); err != nil {
@@ -156,46 +190,37 @@ func NewRSRParser(parserRules string, allFiltersMatch bool) (rsrParser *RSRParse
convsSplt := strings.Split(convertersStr, utils.ANDSep)
rsrParser.converters = make(utils.DataConverters, len(convsSplt))
for i, convStr := range convsSplt {
if conv, err := utils.NewDataConverter(convStr); err != nil {
var conv utils.DataConverter
if conv, err = utils.NewDataConverter(convStr); err != nil {
return nil,
fmt.Errorf("invalid converter value in string: <%s>, err: %s",
convStr, err.Error())
} else {
rsrParser.converters[i] = conv
}
rsrParser.converters[i] = conv
}
parserRules = parserRules[:idxConverters]
}
if !strings.HasPrefix(parserRules, utils.DynamicDataPrefix) { // special case when RSR is defined as static attribute=value
var staticHdr, staticVal string
if splt := strings.Split(parserRules, utils.AttrValueSep); len(splt) == 2 { // using '='' as separator since ':' is often use in date/time fields
staticHdr, staticVal = splt[0], splt[1] // strip the separator
if strings.HasSuffix(staticVal, utils.AttrValueSep) { // if value ends with sep, strip it since it is a part of the definition syntax
staticVal = staticVal[:len(staticVal)-1]
}
} else if len(splt) > 2 {
return nil, fmt.Errorf("invalid RSRField static rules: <%s>", parserRules)
} else {
staticVal = splt[0] // no attribute name
}
rsrParser.attrName = staticHdr
rsrParser.attrValue = staticVal
if !strings.HasPrefix(parserRules, utils.DynamicDataPrefix) ||
len(parserRules) == 1 { // special case when RSR is defined as static attribute
return
}
// dynamic content via attributeNames
spltRules := spltRgxp.Split(parserRules, -1)
rsrParser.attrName = spltRules[0][1:] // in form ~hdr_name
rsrParser.path = spltRules[0][1:] // in form ~hdr_name
if len(spltRules) > 1 {
for _, ruleStr := range spltRules[1:] { // :s/ already removed through split
allMatches := rulesRgxp.FindStringSubmatch(ruleStr)
if len(allMatches) != 3 {
return nil, fmt.Errorf("not enough members in Search&Replace, ruleStr: <%s>, matches: %v, ", ruleStr, allMatches)
}
if srRegexp, err := regexp.Compile(allMatches[1]); err != nil {
var srRegexp *regexp.Regexp
if srRegexp, err = regexp.Compile(allMatches[1]); err != nil {
return nil, fmt.Errorf("invalid Search&Replace subfield rule: <%s>", allMatches[1])
} else {
rsrParser.rsrRules = append(rsrParser.rsrRules, &utils.ReSearchReplace{SearchRegexp: srRegexp, ReplaceTemplate: allMatches[2]})
}
rsrParser.rsrRules = append(rsrParser.rsrRules, &utils.ReSearchReplace{
SearchRegexp: srRegexp,
ReplaceTemplate: allMatches[2],
})
}
}
return
@@ -214,8 +239,7 @@ type RSRParser struct {
Rules string // Rules container holding the string rules, public so it can be stored
AllFiltersMatch bool // all filters must match policy
attrName string // instruct extracting info out of header in event
attrValue string // if populated, enforces parsing always to this value
path string // instruct extracting info out of header in event
rsrRules []*utils.ReSearchReplace // rules to use when parsing value
converters utils.DataConverters // set of converters to apply on output
filters utils.RSRFilters // The value to compare when used as filter
@@ -223,7 +247,7 @@ type RSRParser struct {
// AttrName exports the attribute name of the RSRParser
func (prsr *RSRParser) AttrName() string {
return prsr.attrName
return prsr.path
}
// Compile parses Rules string and repopulates other fields
@@ -250,8 +274,8 @@ func (prsr *RSRParser) RegexpMatched() bool {
// parseValue the field value from a string
func (prsr *RSRParser) parseValue(value string) string {
if prsr.attrValue != "" { // Enforce parsing of static values
return prsr.attrValue
if prsr.path == "" { // Enforce parsing of static values
return prsr.Rules
}
for _, rsRule := range prsr.rsrRules {
value = rsRule.Process(value)
@@ -271,20 +295,11 @@ func (prsr *RSRParser) ParseValue(value interface{}) (out string, err error) {
return
}
// ParseEvent will parse the value out considering converters and filters
func (prsr *RSRParser) ParseEvent(ev map[string]interface{}) (out string, err error) {
val, has := ev[prsr.attrName]
if !has && prsr.attrValue == "" {
return "", utils.ErrNotFound
}
return prsr.ParseValue(val)
}
func (prsr *RSRParser) ParseDataProvider(dP utils.DataProvider, separator string) (out string, err error) {
var outStr string
if prsr.attrValue == "" {
if prsr.path != "" {
if outStr, err = dP.FieldAsString(
strings.Split(prsr.attrName, separator)); err != nil &&
strings.Split(prsr.path, separator)); err != nil &&
(err != utils.ErrNotFound || prsr.filters.FilterRules() != "^$") {
return
}
@@ -294,9 +309,9 @@ func (prsr *RSRParser) ParseDataProvider(dP utils.DataProvider, separator string
func (prsr *RSRParser) ParseDataProviderWithInterfaces(dP utils.DataProvider, separator string) (out string, err error) {
var outIface interface{}
if prsr.attrValue == "" {
if prsr.path != "" {
if outIface, err = dP.FieldAsInterface(
strings.Split(prsr.attrName, separator)); err != nil &&
strings.Split(prsr.path, separator)); err != nil &&
(err != utils.ErrNotFound || prsr.filters.FilterRules() != "^$") {
return
}

View File

@@ -27,18 +27,18 @@ import (
)
func TestNewRSRParsers(t *testing.T) {
ruleStr := `Value1;Heade2=Value2;~Header3(Val3&!Val4);~Header4:s/a/${1}b/{*duration_seconds&*round:2}(b&c);Value5{*duration_seconds&*round:2}`
ruleStr := `Value1;Value2;~Header3(Val3&!Val4);~Header4:s/a/${1}b/{*duration_seconds&*round:2}(b&c);Value5{*duration_seconds&*round:2}`
eRSRParsers := RSRParsers{
&RSRParser{Rules: "Value1", AllFiltersMatch: true, attrValue: "Value1"},
&RSRParser{Rules: "Heade2=Value2", AllFiltersMatch: true, attrName: "Heade2", attrValue: "Value2"},
&RSRParser{Rules: "~Header3(Val3&!Val4)", AllFiltersMatch: true, attrName: "Header3",
&RSRParser{Rules: "Value1", AllFiltersMatch: true},
&RSRParser{Rules: "Value2", AllFiltersMatch: true},
&RSRParser{Rules: "~Header3(Val3&!Val4)", AllFiltersMatch: true, path: "Header3",
filters: utils.RSRFilters{utils.NewRSRFilterMustCompile("Val3"),
utils.NewRSRFilterMustCompile("!Val4")}},
&RSRParser{Rules: "~Header4:s/a/${1}b/{*duration_seconds&*round:2}(b&c)", AllFiltersMatch: true,
attrName: "Header4",
path: "Header4",
rsrRules: []*utils.ReSearchReplace{
&utils.ReSearchReplace{
{
SearchRegexp: regexp.MustCompile(`a`),
ReplaceTemplate: "${1}b"}},
converters: utils.DataConverters{utils.NewDataConverterMustCompile("*duration_seconds"),
@@ -48,7 +48,6 @@ func TestNewRSRParsers(t *testing.T) {
},
&RSRParser{Rules: "Value5{*duration_seconds&*round:2}", AllFiltersMatch: true,
attrValue: "Value5",
converters: utils.DataConverters{utils.NewDataConverterMustCompile("*duration_seconds"),
utils.NewDataConverterMustCompile("*round:2")},
},
@@ -62,10 +61,10 @@ func TestNewRSRParsers(t *testing.T) {
func TestRSRParserCompile(t *testing.T) {
ePrsr := &RSRParser{
Rules: "~Header4:s/a/${1}b/{*duration_seconds&*round:2}(b&c)",
attrName: "Header4",
Rules: "~Header4:s/a/${1}b/{*duration_seconds&*round:2}(b&c)",
path: "Header4",
rsrRules: []*utils.ReSearchReplace{
&utils.ReSearchReplace{
{
SearchRegexp: regexp.MustCompile(`a`),
ReplaceTemplate: "${1}b"}},
converters: utils.DataConverters{utils.NewDataConverterMustCompile("*duration_seconds"),
@@ -83,20 +82,6 @@ func TestRSRParserCompile(t *testing.T) {
}
}
func TestRSRParsersParseEvent(t *testing.T) {
prsrs := NewRSRParsersMustCompile("~Header1;|;~Header2", true, utils.INFIELD_SEP)
ev := map[string]interface{}{
"Header1": "Value1",
"Header2": "Value2",
}
eOut := "Value1|Value2"
if out, err := prsrs.ParseEvent(ev); err != nil {
t.Error(err)
} else if eOut != out {
t.Errorf("expecting: %s, received: %s", eOut, out)
}
}
func TestRSRParserConstant(t *testing.T) {
rule := "cgrates.org"
rsrParsers, err := NewRSRParsers(rule, true, utils.INFIELD_SEP)
@@ -123,36 +108,6 @@ func TestRSRParserNotConstant(t *testing.T) {
}
}
func TestRSRParsersParseEvent2(t *testing.T) {
prsrs := NewRSRParsersMustCompile("~Header1.Test;|;~Header2.Test", true, utils.INFIELD_SEP)
ev := map[string]interface{}{
"Header1.Test": "Value1",
"Header2.Test": "Value2",
}
eOut := "Value1|Value2"
if out, err := prsrs.ParseEvent(ev); err != nil {
t.Error(err)
} else if eOut != out {
t.Errorf("expecting: %s, received: %s", eOut, out)
}
}
func TestRSRParsersParseEvent3(t *testing.T) {
prsr, err := NewRSRParser("~Category:s/(.*)/${1}_suffix/", true)
if err != nil {
t.Error(err)
}
ev := map[string]interface{}{
"Category": "call",
}
eOut := "call_suffix"
if out, err := prsr.ParseEvent(ev); err != nil {
t.Error(err)
} else if eOut != out {
t.Errorf("expecting: %s, received: %s", eOut, out)
}
}
// TestRSRParsersParseInnerBraces makes sure the inner braces are allowed in a filter rule
func TestRSRParsersParseInnerBracket(t *testing.T) {
rule := "~*req.Service-Information.IN-Information.CalledPartyAddress(~^(00)*(33|0)890240004$)"
@@ -165,3 +120,64 @@ func TestRSRParsersParseInnerBracket(t *testing.T) {
t.Errorf("expecting: %s, received: %s", expAttrName, prsr.AttrName())
}
}
func TestNewRSRParsersConstant(t *testing.T) {
ruleStr := "`>;q=0.7;expires=3600`"
eRSRParsers := RSRParsers{
&RSRParser{Rules: ">;q=0.7;expires=3600", AllFiltersMatch: true},
}
if rsrParsers, err := NewRSRParsers(ruleStr, true, utils.INFIELD_SEP); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if !reflect.DeepEqual(eRSRParsers, rsrParsers) {
t.Errorf("expecting: %+v, received: %+v", eRSRParsers, rsrParsers)
} else if out, err := rsrParsers.ParseDataProvider(utils.MapStorage{}, utils.NestingSep); err != nil {
t.Error(err)
} else if expected := ">;q=0.7;expires=3600"; out != expected {
t.Errorf("Expected %+v ,received %+v", expected, out)
}
}
func TestNewRSRParsersConstant2(t *testing.T) {
ruleStr := "constant;something`>;q=0.7;expires=3600`new;constant"
if rsrParsers, err := NewRSRParsers(ruleStr, true, utils.INFIELD_SEP); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if out, err := rsrParsers.ParseDataProvider(utils.MapStorage{}, utils.NestingSep); err != nil {
t.Error(err)
} else if expected := "constantsomething>;q=0.7;expires=3600newconstant"; out != expected {
t.Errorf("Expected %q ,received %q", expected, out)
}
ruleStr = "constant;`>;q=0.7;expires=3600`;constant"
if rsrParsers, err := NewRSRParsers(ruleStr, true, utils.INFIELD_SEP); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if out, err := rsrParsers.ParseDataProvider(utils.MapStorage{}, utils.NestingSep); err != nil {
t.Error(err)
} else if expected := "constant>;q=0.7;expires=3600constant"; out != expected {
t.Errorf("Expected %q ,received %q", expected, out)
}
ruleStr = "constant;`>;q=0.7;expires=3600`constant"
if rsrParsers, err := NewRSRParsers(ruleStr, true, utils.INFIELD_SEP); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if out, err := rsrParsers.ParseDataProvider(utils.MapStorage{}, utils.NestingSep); err != nil {
t.Error(err)
} else if expected := "constant>;q=0.7;expires=3600constant"; out != expected {
t.Errorf("Expected %q ,received %q", expected, out)
}
}
func TestRSRParserCompileConstant(t *testing.T) {
ePrsr := &RSRParser{
Rules: "*constant:>;q=0.7;expires=3600",
AllFiltersMatch: true,
}
prsr := &RSRParser{
Rules: "*constant:>;q=0.7;expires=3600",
AllFiltersMatch: true,
}
if err := prsr.Compile(); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(ePrsr, prsr) {
t.Errorf("expecting: %+v, received: %+v", ePrsr, prsr)
}
}

View File

@@ -95,7 +95,6 @@ func (dbcfg *StorDbCfg) loadFromJsonCfg(jsnDbCfg *DbJsonCfg) (err error) {
dbcfg.SSLMode = *jsnDbCfg.Sslmode
}
if jsnDbCfg.Items != nil {
dbcfg.Items = make(map[string]*ItemOpt)
for kJsn, vJsn := range *jsnDbCfg.Items {
val := new(ItemOpt)
if err := val.loadFromJsonCfg(vJsn); err != nil {

View File

@@ -135,6 +135,7 @@ func TestStoreDbCfgloadFromJsonCfgPort(t *testing.T) {
func TestStorDbCfgAsMapInterface(t *testing.T) {
var dbcfg StorDbCfg
dbcfg.Items = make(map[string]*ItemOpt)
cfgJSONStr := `{
"stor_db": {
"db_type": "*mysql",

View File

@@ -257,6 +257,7 @@ func (me MapEvent) AsCDR(cfg *config.CGRConfig, tnt, tmz string) (cdr *CDR, err
if cdr.CostDetails, err = IfaceAsEventCost(v); err != nil {
return nil, err
}
cdr.CostDetails.initCache()
case utils.ExtraInfo:
cdr.ExtraInfo = utils.IfaceAsString(v)
case utils.OrderID:
@@ -265,11 +266,6 @@ func (me MapEvent) AsCDR(cfg *config.CGRConfig, tnt, tmz string) (cdr *CDR, err
}
}
}
if cdr.CostDetails == nil {
cdr.CostDetails = NewBareEventCost()
} else {
cdr.CostDetails.initCache()
}
if cfg != nil {
cdr.AddDefaults(cfg)
}

View File

@@ -311,7 +311,7 @@ func TestMapEventAsMapString(t *testing.T) {
func TestMapEventAsCDR(t *testing.T) {
me := NewMapEvent(nil)
expected := &CDR{Cost: -1.0, ExtraFields: make(map[string]string), CostDetails: NewBareEventCost()}
expected := &CDR{Cost: -1.0, ExtraFields: make(map[string]string)}
if rply, err := me.AsCDR(nil, utils.EmptyString, utils.EmptyString); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expected, rply) {
@@ -330,7 +330,6 @@ func TestMapEventAsCDR(t *testing.T) {
Tenant: cfg.GeneralCfg().DefaultTenant,
Category: cfg.GeneralCfg().DefaultCategory,
ExtraFields: make(map[string]string),
CostDetails: NewBareEventCost(),
}
if rply, err := me.AsCDR(cfg, utils.EmptyString, utils.EmptyString); err != nil {
t.Error(err)
@@ -372,8 +371,7 @@ func TestMapEventAsCDR(t *testing.T) {
me = MapEvent{"ExtraField1": 5, "ExtraField2": "extra"}
expected = &CDR{
Cost: -1.0,
CostDetails: NewBareEventCost(),
Cost: -1.0,
ExtraFields: map[string]string{
"ExtraField1": "5",
"ExtraField2": "extra",
@@ -405,7 +403,6 @@ func TestMapEventAsCDR(t *testing.T) {
Tenant: cfg.GeneralCfg().DefaultTenant,
Category: cfg.GeneralCfg().DefaultCategory,
ExtraInfo: "ACCOUNT_NOT_FOUND",
CostDetails: NewBareEventCost(),
}
if rply, err := me.AsCDR(cfg, utils.EmptyString, utils.EmptyString); err != nil {
t.Error(err)
@@ -449,8 +446,7 @@ func TestMapEventAsCDR(t *testing.T) {
"ExtraField1": "5",
"ExtraField2": "extra",
},
ExtraInfo: "ACCOUNT_NOT_FOUND",
CostDetails: NewBareEventCost(),
ExtraInfo: "ACCOUNT_NOT_FOUND",
}
if rply, err := me.AsCDR(cfg, utils.EmptyString, utils.EmptyString); err != nil {
t.Error(err)

View File

@@ -625,7 +625,7 @@ func TestSafEventAsMapString(t *testing.T) {
func TestSafEventAsCDR(t *testing.T) {
se := SafEvent{Me: NewMapEvent(nil)}
expected := &CDR{Cost: -1.0, ExtraFields: make(map[string]string), CostDetails: NewBareEventCost()}
expected := &CDR{Cost: -1.0, ExtraFields: make(map[string]string)}
if rply, err := se.AsCDR(nil, utils.EmptyString, utils.EmptyString); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expected, rply) {
@@ -644,7 +644,6 @@ func TestSafEventAsCDR(t *testing.T) {
Tenant: cfg.GeneralCfg().DefaultTenant,
Category: cfg.GeneralCfg().DefaultCategory,
ExtraFields: make(map[string]string),
CostDetails: NewBareEventCost(),
}
if rply, err := se.AsCDR(cfg, utils.EmptyString, utils.EmptyString); err != nil {
t.Error(err)
@@ -677,8 +676,7 @@ func TestSafEventAsCDR(t *testing.T) {
}
se = SafEvent{Me: MapEvent{"ExtraField1": 5, "ExtraField2": "extra"}}
expected = &CDR{
Cost: -1.0,
CostDetails: NewBareEventCost(),
Cost: -1.0,
ExtraFields: map[string]string{
"ExtraField1": "5",
"ExtraField2": "extra",
@@ -708,7 +706,6 @@ func TestSafEventAsCDR(t *testing.T) {
RequestType: cfg.GeneralCfg().DefaultReqType,
Tenant: cfg.GeneralCfg().DefaultTenant,
Category: cfg.GeneralCfg().DefaultCategory,
CostDetails: NewBareEventCost(),
}
if rply, err := se.AsCDR(cfg, utils.EmptyString, utils.EmptyString); err != nil {
t.Error(err)
@@ -742,7 +739,6 @@ func TestSafEventAsCDR(t *testing.T) {
ToR: utils.VOICE,
RequestType: cfg.GeneralCfg().DefaultReqType,
Category: cfg.GeneralCfg().DefaultCategory,
CostDetails: NewBareEventCost(),
}
if rply, err := se.AsCDR(cfg, "itsyscom.com", utils.EmptyString); err != nil {
t.Error(err)

View File

@@ -34,158 +34,158 @@ import (
func newInternalDBCfg(itemsCacheCfg map[string]*config.ItemOpt, isDataDB bool) map[string]*ltcache.CacheConfig {
if isDataDB {
return map[string]*ltcache.CacheConfig{
utils.CacheDestinations: &ltcache.CacheConfig{
utils.CacheDestinations: {
MaxItems: itemsCacheCfg[utils.CacheDestinations].Limit,
TTL: itemsCacheCfg[utils.CacheDestinations].TTL,
StaticTTL: itemsCacheCfg[utils.CacheDestinations].StaticTTL,
},
utils.CacheReverseDestinations: &ltcache.CacheConfig{
utils.CacheReverseDestinations: {
MaxItems: itemsCacheCfg[utils.CacheReverseDestinations].Limit,
TTL: itemsCacheCfg[utils.CacheReverseDestinations].TTL,
StaticTTL: itemsCacheCfg[utils.CacheReverseDestinations].StaticTTL,
},
utils.CacheActions: &ltcache.CacheConfig{
utils.CacheActions: {
MaxItems: itemsCacheCfg[utils.CacheActions].Limit,
TTL: itemsCacheCfg[utils.CacheActions].TTL,
StaticTTL: itemsCacheCfg[utils.CacheActions].StaticTTL,
},
utils.CacheActionPlans: &ltcache.CacheConfig{
utils.CacheActionPlans: {
MaxItems: itemsCacheCfg[utils.CacheActionPlans].Limit,
TTL: itemsCacheCfg[utils.CacheActionPlans].TTL,
StaticTTL: itemsCacheCfg[utils.CacheActionPlans].StaticTTL,
},
utils.CacheAccountActionPlans: &ltcache.CacheConfig{
utils.CacheAccountActionPlans: {
MaxItems: itemsCacheCfg[utils.CacheAccountActionPlans].Limit,
TTL: itemsCacheCfg[utils.CacheAccountActionPlans].TTL,
StaticTTL: itemsCacheCfg[utils.CacheAccountActionPlans].StaticTTL,
},
utils.CacheActionTriggers: &ltcache.CacheConfig{
utils.CacheActionTriggers: {
MaxItems: itemsCacheCfg[utils.CacheActionTriggers].Limit,
TTL: itemsCacheCfg[utils.CacheActionTriggers].TTL,
StaticTTL: itemsCacheCfg[utils.CacheActionTriggers].StaticTTL,
},
utils.CacheRatingPlans: &ltcache.CacheConfig{
utils.CacheRatingPlans: {
MaxItems: itemsCacheCfg[utils.CacheRatingPlans].Limit,
TTL: itemsCacheCfg[utils.CacheRatingPlans].TTL,
StaticTTL: itemsCacheCfg[utils.CacheRatingPlans].StaticTTL,
},
utils.CacheRatingProfiles: &ltcache.CacheConfig{
utils.CacheRatingProfiles: {
MaxItems: itemsCacheCfg[utils.CacheRatingProfiles].Limit,
TTL: itemsCacheCfg[utils.CacheRatingProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.CacheRatingProfiles].StaticTTL,
},
utils.CacheAccounts: &ltcache.CacheConfig{
utils.CacheAccounts: {
MaxItems: itemsCacheCfg[utils.CacheAccounts].Limit,
TTL: itemsCacheCfg[utils.CacheAccounts].TTL,
StaticTTL: itemsCacheCfg[utils.CacheAccounts].StaticTTL,
},
utils.CacheSharedGroups: &ltcache.CacheConfig{
utils.CacheSharedGroups: {
MaxItems: itemsCacheCfg[utils.CacheSharedGroups].Limit,
TTL: itemsCacheCfg[utils.CacheSharedGroups].TTL,
StaticTTL: itemsCacheCfg[utils.CacheSharedGroups].StaticTTL,
},
utils.CacheTimings: &ltcache.CacheConfig{
utils.CacheTimings: {
MaxItems: itemsCacheCfg[utils.CacheTimings].Limit,
TTL: itemsCacheCfg[utils.CacheTimings].TTL,
StaticTTL: itemsCacheCfg[utils.CacheTimings].StaticTTL,
},
utils.CacheFilters: &ltcache.CacheConfig{
utils.CacheFilters: {
MaxItems: itemsCacheCfg[utils.CacheFilters].Limit,
TTL: itemsCacheCfg[utils.CacheFilters].TTL,
StaticTTL: itemsCacheCfg[utils.CacheFilters].StaticTTL,
},
utils.CacheResourceProfiles: &ltcache.CacheConfig{
utils.CacheResourceProfiles: {
MaxItems: itemsCacheCfg[utils.CacheResourceProfiles].Limit,
TTL: itemsCacheCfg[utils.CacheResourceProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.CacheResourceProfiles].StaticTTL,
},
utils.CacheResourceFilterIndexes: &ltcache.CacheConfig{
utils.CacheResourceFilterIndexes: {
MaxItems: itemsCacheCfg[utils.MetaFilterIndexes].Limit,
TTL: itemsCacheCfg[utils.MetaFilterIndexes].TTL,
StaticTTL: itemsCacheCfg[utils.MetaFilterIndexes].StaticTTL,
},
utils.CacheResources: &ltcache.CacheConfig{
utils.CacheResources: {
MaxItems: itemsCacheCfg[utils.CacheResources].Limit,
TTL: itemsCacheCfg[utils.CacheResources].TTL,
StaticTTL: itemsCacheCfg[utils.CacheResources].StaticTTL,
},
utils.CacheStatFilterIndexes: &ltcache.CacheConfig{
utils.CacheStatFilterIndexes: {
MaxItems: itemsCacheCfg[utils.MetaFilterIndexes].Limit,
TTL: itemsCacheCfg[utils.MetaFilterIndexes].TTL,
StaticTTL: itemsCacheCfg[utils.MetaFilterIndexes].StaticTTL,
},
utils.CacheStatQueueProfiles: &ltcache.CacheConfig{
utils.CacheStatQueueProfiles: {
MaxItems: itemsCacheCfg[utils.CacheStatQueueProfiles].Limit,
TTL: itemsCacheCfg[utils.CacheStatQueueProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.CacheStatQueueProfiles].StaticTTL,
},
utils.CacheStatQueues: &ltcache.CacheConfig{
utils.CacheStatQueues: {
MaxItems: itemsCacheCfg[utils.CacheStatQueues].Limit,
TTL: itemsCacheCfg[utils.CacheStatQueues].TTL,
StaticTTL: itemsCacheCfg[utils.CacheStatQueues].StaticTTL,
},
utils.CacheThresholdFilterIndexes: &ltcache.CacheConfig{
utils.CacheThresholdFilterIndexes: {
MaxItems: itemsCacheCfg[utils.MetaFilterIndexes].Limit,
TTL: itemsCacheCfg[utils.MetaFilterIndexes].TTL,
StaticTTL: itemsCacheCfg[utils.MetaFilterIndexes].StaticTTL,
},
utils.CacheThresholdProfiles: &ltcache.CacheConfig{
utils.CacheThresholdProfiles: {
MaxItems: itemsCacheCfg[utils.CacheThresholdProfiles].Limit,
TTL: itemsCacheCfg[utils.CacheThresholdProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.CacheThresholdProfiles].StaticTTL,
},
utils.CacheThresholds: &ltcache.CacheConfig{
utils.CacheThresholds: {
MaxItems: itemsCacheCfg[utils.CacheThresholds].Limit,
TTL: itemsCacheCfg[utils.CacheThresholds].TTL,
StaticTTL: itemsCacheCfg[utils.CacheThresholds].StaticTTL,
},
utils.CacheSupplierFilterIndexes: &ltcache.CacheConfig{
utils.CacheSupplierFilterIndexes: {
MaxItems: itemsCacheCfg[utils.MetaFilterIndexes].Limit,
TTL: itemsCacheCfg[utils.MetaFilterIndexes].TTL,
StaticTTL: itemsCacheCfg[utils.MetaFilterIndexes].StaticTTL,
},
utils.CacheSupplierProfiles: &ltcache.CacheConfig{
utils.CacheSupplierProfiles: {
MaxItems: itemsCacheCfg[utils.CacheSupplierProfiles].Limit,
TTL: itemsCacheCfg[utils.CacheSupplierProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.CacheSupplierProfiles].StaticTTL,
},
utils.CacheChargerFilterIndexes: &ltcache.CacheConfig{
utils.CacheChargerFilterIndexes: {
MaxItems: itemsCacheCfg[utils.MetaFilterIndexes].Limit,
TTL: itemsCacheCfg[utils.MetaFilterIndexes].TTL,
StaticTTL: itemsCacheCfg[utils.MetaFilterIndexes].StaticTTL,
},
utils.CacheChargerProfiles: &ltcache.CacheConfig{
utils.CacheChargerProfiles: {
MaxItems: itemsCacheCfg[utils.CacheChargerProfiles].Limit,
TTL: itemsCacheCfg[utils.CacheChargerProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.CacheChargerProfiles].StaticTTL,
},
utils.CacheAttributeFilterIndexes: &ltcache.CacheConfig{
utils.CacheAttributeFilterIndexes: {
MaxItems: itemsCacheCfg[utils.MetaFilterIndexes].Limit,
TTL: itemsCacheCfg[utils.MetaFilterIndexes].TTL,
StaticTTL: itemsCacheCfg[utils.MetaFilterIndexes].StaticTTL,
},
utils.CacheAttributeProfiles: &ltcache.CacheConfig{
utils.CacheAttributeProfiles: {
MaxItems: itemsCacheCfg[utils.CacheAttributeProfiles].Limit,
TTL: itemsCacheCfg[utils.CacheAttributeProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.CacheAttributeProfiles].StaticTTL,
},
utils.CacheDispatcherFilterIndexes: &ltcache.CacheConfig{
utils.CacheDispatcherFilterIndexes: {
MaxItems: itemsCacheCfg[utils.MetaFilterIndexes].Limit,
TTL: itemsCacheCfg[utils.MetaFilterIndexes].TTL,
StaticTTL: itemsCacheCfg[utils.MetaFilterIndexes].StaticTTL,
},
utils.CacheDispatcherProfiles: &ltcache.CacheConfig{
utils.CacheDispatcherProfiles: {
MaxItems: itemsCacheCfg[utils.CacheDispatcherProfiles].Limit,
TTL: itemsCacheCfg[utils.CacheDispatcherProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.CacheDispatcherProfiles].StaticTTL,
},
utils.CacheDispatcherHosts: &ltcache.CacheConfig{
utils.CacheDispatcherHosts: {
MaxItems: itemsCacheCfg[utils.CacheDispatcherHosts].Limit,
TTL: itemsCacheCfg[utils.CacheDispatcherHosts].TTL,
StaticTTL: itemsCacheCfg[utils.CacheDispatcherHosts].StaticTTL,
},
utils.CacheLoadIDs: &ltcache.CacheConfig{
utils.CacheLoadIDs: {
MaxItems: itemsCacheCfg[utils.CacheLoadIDs].Limit,
TTL: itemsCacheCfg[utils.CacheLoadIDs].TTL,
StaticTTL: itemsCacheCfg[utils.CacheLoadIDs].StaticTTL,
@@ -193,117 +193,117 @@ func newInternalDBCfg(itemsCacheCfg map[string]*config.ItemOpt, isDataDB bool) m
}
} else {
return map[string]*ltcache.CacheConfig{
utils.TBLVersions: &ltcache.CacheConfig{
utils.TBLVersions: {
MaxItems: itemsCacheCfg[utils.TBLVersions].Limit,
TTL: itemsCacheCfg[utils.TBLVersions].TTL,
StaticTTL: itemsCacheCfg[utils.TBLVersions].StaticTTL,
},
utils.TBLTPTimings: &ltcache.CacheConfig{
utils.TBLTPTimings: {
MaxItems: itemsCacheCfg[utils.TBLTPTimings].Limit,
TTL: itemsCacheCfg[utils.TBLTPTimings].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPTimings].StaticTTL,
},
utils.TBLTPDestinations: &ltcache.CacheConfig{
utils.TBLTPDestinations: {
MaxItems: itemsCacheCfg[utils.TBLTPDestinations].Limit,
TTL: itemsCacheCfg[utils.TBLTPDestinations].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPDestinations].StaticTTL,
},
utils.TBLTPRates: &ltcache.CacheConfig{
utils.TBLTPRates: {
MaxItems: itemsCacheCfg[utils.TBLTPRates].Limit,
TTL: itemsCacheCfg[utils.TBLTPRates].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPRates].StaticTTL,
},
utils.TBLTPDestinationRates: &ltcache.CacheConfig{
utils.TBLTPDestinationRates: {
MaxItems: itemsCacheCfg[utils.TBLTPDestinationRates].Limit,
TTL: itemsCacheCfg[utils.TBLTPDestinationRates].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPDestinationRates].StaticTTL,
},
utils.TBLTPRatingPlans: &ltcache.CacheConfig{
utils.TBLTPRatingPlans: {
MaxItems: itemsCacheCfg[utils.TBLTPRatingPlans].Limit,
TTL: itemsCacheCfg[utils.TBLTPRatingPlans].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPRatingPlans].StaticTTL,
},
utils.TBLTPRateProfiles: &ltcache.CacheConfig{
utils.TBLTPRateProfiles: {
MaxItems: itemsCacheCfg[utils.TBLTPRateProfiles].Limit,
TTL: itemsCacheCfg[utils.TBLTPRateProfiles].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPRateProfiles].StaticTTL,
},
utils.TBLTPSharedGroups: &ltcache.CacheConfig{
utils.TBLTPSharedGroups: {
MaxItems: itemsCacheCfg[utils.TBLTPSharedGroups].Limit,
TTL: itemsCacheCfg[utils.TBLTPSharedGroups].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPSharedGroups].StaticTTL,
},
utils.TBLTPActions: &ltcache.CacheConfig{
utils.TBLTPActions: {
MaxItems: itemsCacheCfg[utils.TBLTPActions].Limit,
TTL: itemsCacheCfg[utils.TBLTPActions].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPActions].StaticTTL,
},
utils.TBLTPActionTriggers: &ltcache.CacheConfig{
utils.TBLTPActionTriggers: {
MaxItems: itemsCacheCfg[utils.TBLTPActionTriggers].Limit,
TTL: itemsCacheCfg[utils.TBLTPActionTriggers].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPActionTriggers].StaticTTL,
},
utils.TBLTPAccountActions: &ltcache.CacheConfig{
utils.TBLTPAccountActions: {
MaxItems: itemsCacheCfg[utils.TBLTPAccountActions].Limit,
TTL: itemsCacheCfg[utils.TBLTPAccountActions].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPAccountActions].StaticTTL,
},
utils.TBLTPResources: &ltcache.CacheConfig{
utils.TBLTPResources: {
MaxItems: itemsCacheCfg[utils.TBLTPResources].Limit,
TTL: itemsCacheCfg[utils.TBLTPResources].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPResources].StaticTTL,
},
utils.TBLTPStats: &ltcache.CacheConfig{
utils.TBLTPStats: {
MaxItems: itemsCacheCfg[utils.TBLTPStats].Limit,
TTL: itemsCacheCfg[utils.TBLTPStats].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPStats].StaticTTL,
},
utils.TBLTPThresholds: &ltcache.CacheConfig{
utils.TBLTPThresholds: {
MaxItems: itemsCacheCfg[utils.TBLTPThresholds].Limit,
TTL: itemsCacheCfg[utils.TBLTPThresholds].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPThresholds].StaticTTL,
},
utils.TBLTPFilters: &ltcache.CacheConfig{
utils.TBLTPFilters: {
MaxItems: itemsCacheCfg[utils.TBLTPFilters].Limit,
TTL: itemsCacheCfg[utils.TBLTPFilters].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPFilters].StaticTTL,
},
utils.SessionCostsTBL: &ltcache.CacheConfig{
utils.SessionCostsTBL: {
MaxItems: itemsCacheCfg[utils.SessionCostsTBL].Limit,
TTL: itemsCacheCfg[utils.SessionCostsTBL].TTL,
StaticTTL: itemsCacheCfg[utils.SessionCostsTBL].StaticTTL,
},
utils.TBLTPActionPlans: &ltcache.CacheConfig{
utils.TBLTPActionPlans: {
MaxItems: itemsCacheCfg[utils.TBLTPActionPlans].Limit,
TTL: itemsCacheCfg[utils.TBLTPActionPlans].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPActionPlans].StaticTTL,
},
utils.TBLTPSuppliers: &ltcache.CacheConfig{
utils.TBLTPSuppliers: {
MaxItems: itemsCacheCfg[utils.TBLTPSuppliers].Limit,
TTL: itemsCacheCfg[utils.TBLTPSuppliers].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPSuppliers].StaticTTL,
},
utils.TBLTPAttributes: &ltcache.CacheConfig{
utils.TBLTPAttributes: {
MaxItems: itemsCacheCfg[utils.TBLTPAttributes].Limit,
TTL: itemsCacheCfg[utils.TBLTPAttributes].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPAttributes].StaticTTL,
},
utils.TBLTPChargers: &ltcache.CacheConfig{
utils.TBLTPChargers: {
MaxItems: itemsCacheCfg[utils.TBLTPChargers].Limit,
TTL: itemsCacheCfg[utils.TBLTPChargers].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPChargers].StaticTTL,
},
utils.TBLTPDispatchers: &ltcache.CacheConfig{
utils.TBLTPDispatchers: {
MaxItems: itemsCacheCfg[utils.TBLTPDispatchers].Limit,
TTL: itemsCacheCfg[utils.TBLTPDispatchers].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPDispatchers].StaticTTL,
},
utils.TBLTPDispatcherHosts: &ltcache.CacheConfig{
utils.TBLTPDispatcherHosts: {
MaxItems: itemsCacheCfg[utils.TBLTPDispatcherHosts].Limit,
TTL: itemsCacheCfg[utils.TBLTPDispatcherHosts].TTL,
StaticTTL: itemsCacheCfg[utils.TBLTPDispatcherHosts].StaticTTL,
},
utils.CDRsTBL: &ltcache.CacheConfig{
utils.CDRsTBL: {
MaxItems: itemsCacheCfg[utils.CDRsTBL].Limit,
TTL: itemsCacheCfg[utils.CDRsTBL].TTL,
StaticTTL: itemsCacheCfg[utils.CDRsTBL].StaticTTL,
@@ -501,7 +501,7 @@ func (iDB *InternalDB) GetStorageType() string {
}
func (iDB *InternalDB) IsDBEmpty() (resp bool, err error) {
for cacheInstance, _ := range utils.CacheInstanceToPrefix {
for cacheInstance := range utils.CacheInstanceToPrefix {
if len(iDB.db.GetItemIDs(cacheInstance, utils.EmptyString)) != 0 {
return false, nil
}

View File

@@ -28,53 +28,53 @@ import (
func TestDataUpdateFromCSVOneFile(t *testing.T) {
attrSFlds := []*config.FCTemplate{
&config.FCTemplate{Tag: "TenantID",
{Tag: "TenantID",
Path: "Tenant",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~0", true, utils.INFIELD_SEP),
Mandatory: true},
&config.FCTemplate{Tag: "ProfileID",
{Tag: "ProfileID",
Path: "ID",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~1", true, utils.INFIELD_SEP),
Mandatory: true},
&config.FCTemplate{Tag: "Contexts",
{Tag: "Contexts",
Path: "Contexts",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~2", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "FilterIDs",
{Tag: "FilterIDs",
Path: "FilterIDs",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~3", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "ActivationInterval",
{Tag: "ActivationInterval",
Path: "ActivationInterval",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~4", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Path",
{Tag: "Path",
Path: "Path",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~5", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Initial",
{Tag: "Initial",
Path: "Initial",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~6", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Substitute",
{Tag: "Substitute",
Path: "Substitute",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~7", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Append",
{Tag: "Append",
Path: "Append",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~8", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Weight",
{Tag: "Weight",
Path: "Weight",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~9", true, utils.INFIELD_SEP)},
}
rows := [][]string{
[]string{"cgrates.org", "ATTR_1", "*sessions;*cdrs", "*string:Account:1007", "2014-01-14T00:00:00Z", "Account", "*any", "1001", "false", "10"},
[]string{"cgrates.org", "ATTR_1", "", "", "", "Subject", "*any", "1001", "true", ""},
{"cgrates.org", "ATTR_1", "*sessions;*cdrs", "*string:Account:1007", "2014-01-14T00:00:00Z", "Account", "*any", "1001", "false", "10"},
{"cgrates.org", "ATTR_1", "", "", "", "Subject", "*any", "1001", "true", ""},
}
lData := make(LoaderData)
if err := lData.UpdateFromCSV("Attributes.csv", rows[0], attrSFlds,
@@ -118,53 +118,53 @@ func TestDataUpdateFromCSVOneFile(t *testing.T) {
func TestDataUpdateFromCSVOneFile2(t *testing.T) {
attrSFlds := []*config.FCTemplate{
&config.FCTemplate{Tag: "TenantID",
{Tag: "TenantID",
Path: "Tenant",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~0", true, utils.INFIELD_SEP),
Mandatory: true},
&config.FCTemplate{Tag: "ProfileID",
{Tag: "ProfileID",
Path: "ID",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~1", true, utils.INFIELD_SEP),
Mandatory: true},
&config.FCTemplate{Tag: "Contexts",
{Tag: "Contexts",
Path: "Contexts",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~2", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "FilterIDs",
{Tag: "FilterIDs",
Path: "FilterIDs",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~3", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "ActivationInterval",
{Tag: "ActivationInterval",
Path: "ActivationInterval",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~4", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Path",
{Tag: "Path",
Path: "Path",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~5", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Initial",
{Tag: "Initial",
Path: "Initial",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~6", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Substitute",
{Tag: "Substitute",
Path: "Substitute",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~7", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Append",
{Tag: "Append",
Path: "Append",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~8", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Weight",
{Tag: "Weight",
Path: "Weight",
Type: utils.MetaVariable,
Value: config.NewRSRParsersMustCompile("~9", true, utils.INFIELD_SEP)},
}
rows := [][]string{
[]string{"cgrates.org", "ATTR_1", "*sessions;*cdrs", "*string:Account:1007", "2014-01-14T00:00:00Z", "Account", "*any", "1001", "false", "10"},
[]string{"cgrates.org", "ATTR_1", "", "", "", "Subject", "*any", "1001", "true", ""},
{"cgrates.org", "ATTR_1", "*sessions;*cdrs", "*string:Account:1007", "2014-01-14T00:00:00Z", "Account", "*any", "1001", "false", "10"},
{"cgrates.org", "ATTR_1", "", "", "", "Subject", "*any", "1001", "true", ""},
}
lData := make(LoaderData)
if err := lData.UpdateFromCSV("Attributes.csv", rows[0], attrSFlds,
@@ -208,45 +208,45 @@ func TestDataUpdateFromCSVOneFile2(t *testing.T) {
func TestDataUpdateFromCSVMultiFiles(t *testing.T) {
attrSFlds := []*config.FCTemplate{
&config.FCTemplate{Tag: "TenantID",
{Tag: "TenantID",
Path: "Tenant",
Type: utils.MetaString,
Value: config.NewRSRParsersMustCompile("cgrates.org", true, utils.INFIELD_SEP),
Mandatory: true},
&config.FCTemplate{Tag: "ProfileID",
{Tag: "ProfileID",
Path: "ID",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~File2.csv:1", true, utils.INFIELD_SEP),
Mandatory: true},
&config.FCTemplate{Tag: "Contexts",
{Tag: "Contexts",
Path: "Contexts",
Type: utils.MetaString,
Value: config.NewRSRParsersMustCompile("*any", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Path",
{Tag: "Path",
Path: "Path",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~File1.csv:5", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Initial",
{Tag: "Initial",
Path: "Initial",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~File1.csv:6", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Substitute",
{Tag: "Substitute",
Path: "Substitute",
Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~File1.csv:7", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Append",
{Tag: "Append",
Path: "Append",
Type: utils.MetaString,
Value: config.NewRSRParsersMustCompile("true", true, utils.INFIELD_SEP)},
&config.FCTemplate{Tag: "Weight",
{Tag: "Weight",
Path: "Weight",
Type: utils.MetaString,
Value: config.NewRSRParsersMustCompile("10", true, utils.INFIELD_SEP)},
}
loadRun1 := map[string][]string{
"File1.csv": []string{"ignored", "ignored", "ignored", "ignored", "ignored", "Subject", "*any", "1001", "ignored", "ignored"},
"File2.csv": []string{"ignored", "ATTR_1"},
"File1.csv": {"ignored", "ignored", "ignored", "ignored", "ignored", "Subject", "*any", "1001", "ignored", "ignored"},
"File2.csv": {"ignored", "ATTR_1"},
}
lData := make(LoaderData)
for fName, record := range loadRun1 {

View File

@@ -8,6 +8,8 @@ cgrates (0.10.2~dev) UNRELEASED; urgency=medium
* [General] Added *mo+extraDuration time support (e.g. *mo+1h will
be time.Now() + 1 month + 1 hour)
* [SessionS] Use correctly SessionTTLUsage when calculate end usage in case of terminate session from ttl mechanism
* [RSRParsers] Removed attribute sistem from RSRParser
* [RSRParsers] Added grave accent(`) char as a delimiter to not split tge RSR value
-- DanB <danb@cgrates.org> Tue, 12 May 2020 13:08:15 +0300