RSRField - add Rule string so we can retrieve the rule after creation

This commit is contained in:
DanB
2017-02-21 15:58:14 +01:00
parent f648fbdc51
commit aca12543c9
4 changed files with 133 additions and 53 deletions

View File

@@ -128,6 +128,7 @@ func startCdrc(internalCdrSChan, internalRaterChan chan rpcclient.RpcClientConne
if err := cdrc.Run(); err != nil {
utils.Logger.Crit(fmt.Sprintf("Cdrc run error: %s", err.Error()))
exitChan <- true // If run stopped, something is bad, stop the application
return
}
}
@@ -435,6 +436,7 @@ func startHistoryServer(internalHistorySChan chan rpcclient.RpcClientConnection,
if err != nil {
utils.Logger.Crit(fmt.Sprintf("<HistoryServer> Could not start, error: %s", err.Error()))
exitChan <- true
return
}
server.RpcRegisterName("HistoryV1", scribeServer)
internalHistorySChan <- scribeServer
@@ -583,6 +585,7 @@ func main() {
go func() { // Schedule shutdown
time.Sleep(shutdownDur)
exitChan <- true
return
}()
}
// Init config

View File

@@ -19,7 +19,6 @@ package engine
import (
"reflect"
"regexp"
"testing"
"time"
@@ -97,9 +96,7 @@ func TestSearchExtraFieldInSlice(t *testing.T) {
}
func TestSearchReplaceInExtraFields(t *testing.T) {
fsCdrCfg.CDRSExtraFields = []*utils.RSRField{&utils.RSRField{Id: "read_codec"},
&utils.RSRField{Id: "sip_user_agent", RSRules: []*utils.ReSearchReplace{&utils.ReSearchReplace{SearchRegexp: regexp.MustCompile(`([A-Za-z]*).+`), ReplaceTemplate: "$1"}}},
&utils.RSRField{Id: "write_codec"}}
fsCdrCfg.CDRSExtraFields = utils.ParseRSRFieldsMustCompile(`read_codec;~sip_user_agent:s/([A-Za-z]*).+/$1/;write_codec`, utils.INFIELD_SEP)
fsCdr, _ := NewFSCdr(body, fsCdrCfg)
extraFields := fsCdr.getExtraFields()
if len(extraFields) != 3 {
@@ -147,11 +144,11 @@ func TestDDazRSRExtraFields(t *testing.T) {
}`)
var err error
fsCdrCfg, err = config.NewCGRConfigFromJsonString(eFieldsCfg)
expCdrExtra := utils.ParseRSRFieldsMustCompile(`~effective_caller_id_number:s/(\d+)/+$1/`, utils.INFIELD_SEP)
if err != nil {
t.Error("Could not parse the config", err.Error())
} else if !reflect.DeepEqual(fsCdrCfg.CDRSExtraFields, []*utils.RSRField{&utils.RSRField{Id: "effective_caller_id_number",
RSRules: []*utils.ReSearchReplace{&utils.ReSearchReplace{SearchRegexp: regexp.MustCompile(`(\d+)`), ReplaceTemplate: "+$1"}}}}) {
t.Errorf("Unexpected value for config CdrsExtraFields: %v", fsCdrCfg.CDRSExtraFields)
} else if !reflect.DeepEqual(expCdrExtra[0], fsCdrCfg.CDRSExtraFields[0]) { // Kinda deepEqual bug since without index does not match
t.Errorf("Expecting: %+v, received: %+v", expCdrExtra, fsCdrCfg.CDRSExtraFields)
}
fsCdr, err := NewFSCdr(simpleJsonCdr, fsCdrCfg)
if err != nil {
@@ -159,6 +156,6 @@ func TestDDazRSRExtraFields(t *testing.T) {
}
extraFields := fsCdr.getExtraFields()
if extraFields["effective_caller_id_number"] != "+4986517174963" {
t.Error("Unexpected effective_caller_id_number received", extraFields["effective_caller_id_number"])
t.Errorf("Unexpected effective_caller_id_number received: %+v", extraFields["effective_caller_id_number"])
}
}

View File

@@ -27,6 +27,7 @@ func NewRSRField(fldStr string) (*RSRField, error) {
if len(fldStr) == 0 {
return nil, nil
}
rsrField := &RSRField{Rules: fldStr}
var filters []*RSRFilter
if strings.HasSuffix(fldStr, FILTER_VAL_END) { // Has filter, populate the var
fltrStart := strings.LastIndex(fldStr, FILTER_VAL_START)
@@ -43,7 +44,6 @@ func NewRSRField(fldStr string) (*RSRField, error) {
fldStr = fldStr[:fltrStart] // Take the filter part out before compiling further
}
if strings.HasPrefix(fldStr, STATIC_VALUE_PREFIX) { // Special case when RSR is defined as static header/value
var staticHdr, staticVal string
if splt := strings.Split(fldStr, STATIC_HDRVAL_SEP); len(splt) == 2 { // Using / as separator since ':' is often use in date/time fields
@@ -56,17 +56,23 @@ func NewRSRField(fldStr string) (*RSRField, error) {
} else {
staticHdr, staticVal = splt[0][1:], splt[0][1:] // If no split, header will remain as original, value as header without the prefix
}
return &RSRField{Id: staticHdr, staticValue: staticVal, filters: filters}, nil
rsrField.Id = staticHdr
rsrField.staticValue = staticVal
rsrField.filters = filters
return rsrField, nil
}
if !strings.HasPrefix(fldStr, REGEXP_PREFIX) {
return &RSRField{Id: fldStr, filters: filters}, nil
rsrField.Id = fldStr
rsrField.filters = filters
return rsrField, nil
}
spltRgxp := regexp.MustCompile(`:s\/`)
spltRules := spltRgxp.Split(fldStr, -1)
if len(spltRules) < 2 {
return nil, fmt.Errorf("Invalid Split of Search&Replace field rule. %s", fldStr)
}
rsrField := &RSRField{Id: spltRules[0][1:], filters: filters} // Original id in form ~hdr_name
rsrField.Id = spltRules[0][1:]
rsrField.filters = filters // Original id in form ~hdr_name
rulesRgxp := regexp.MustCompile(`(?:(.+[^\\])\/(.*[^\\])*\/){1,}`)
for _, ruleStr := range spltRules[1:] { // :s/ already removed through split
allMatches := rulesRgxp.FindStringSubmatch(ruleStr)
@@ -83,12 +89,30 @@ func NewRSRField(fldStr string) (*RSRField, error) {
}
type RSRField struct {
Id string // Identifier
RSRules []*ReSearchReplace // Rules to use when processing field value
Id string // Identifier
Rules string // Rules container holding the string rules to be able to restore it after DB
staticValue string // If defined, enforces parsing always to this value
RSRules []*ReSearchReplace // Rules to use when processing field value
filters []*RSRFilter // The value to compare when used as filter
}
// IsParsed finds out whether this RSRField was already parsed or RAW state
func (rsrf *RSRField) IsParsed() bool {
return rsrf.staticValue != "" || rsrf.RSRules != nil || rsrf.filters != nil
}
// Compile parses Rules string and repopulates other fields
func (rsrf *RSRField) ParseRules() error {
if newRSRFld, err := NewRSRField(rsrf.Rules); err != nil {
return err
} else {
rsrf.staticValue = newRSRFld.staticValue
rsrf.RSRules = newRSRFld.RSRules
rsrf.filters = newRSRFld.filters
}
return nil
}
// Parse the field value from a string
func (rsrf *RSRField) ParseValue(value string) string {
if len(rsrf.staticValue) != 0 { // Enforce parsing of static values
@@ -218,17 +242,6 @@ func (fltrs RSRFilters) Pass(val string, allMustMatch bool) bool {
return matched
}
// Parses list of RSRFields, used for example as multiple filters in derived charging
func ParseRSRFields(fldsStr, sep string) (RSRFields, error) {
//rsrRlsPattern := regexp.MustCompile(`^(~\w+:s/.+/.*/)|(\^.+(/.+/)?)(;(~\w+:s/.+/.*/)|(\^.+(/.+/)?))*$`) //ToDo:Fix here rule able to confirm the content
if len(fldsStr) == 0 {
return nil, nil
}
rulesSplt := strings.Split(fldsStr, sep)
return ParseRSRFieldsFromSlice(rulesSplt)
}
func ParseRSRFieldsFromSlice(flds []string) (RSRFields, error) {
if len(flds) == 0 {
return nil, nil
@@ -247,6 +260,17 @@ func ParseRSRFieldsFromSlice(flds []string) (RSRFields, error) {
}
// Parses list of RSRFields, used for example as multiple filters in derived charging
func ParseRSRFields(fldsStr, sep string) (RSRFields, error) {
//rsrRlsPattern := regexp.MustCompile(`^(~\w+:s/.+/.*/)|(\^.+(/.+/)?)(;(~\w+:s/.+/.*/)|(\^.+(/.+/)?))*$`) //ToDo:Fix here rule able to confirm the content
if len(fldsStr) == 0 {
return nil, nil
}
rulesSplt := strings.Split(fldsStr, sep)
return ParseRSRFieldsFromSlice(rulesSplt)
}
func ParseRSRFieldsMustCompile(fldsStr, sep string) RSRFields {
if flds, err := ParseRSRFields(fldsStr, sep); err != nil {
return nil

View File

@@ -25,30 +25,34 @@ import (
func TestNewRSRField1(t *testing.T) {
// Normal case
expRSRField1 := &RSRField{Id: "sip_redirected_to",
rulesStr := `~sip_redirected_to:s/sip:\+49(\d+)@/0$1/`
expRSRField1 := &RSRField{Id: "sip_redirected_to", Rules: rulesStr,
RSRules: []*ReSearchReplace{&ReSearchReplace{SearchRegexp: regexp.MustCompile(`sip:\+49(\d+)@`), ReplaceTemplate: "0$1"}}}
if rsrField, err := NewRSRField(`~sip_redirected_to:s/sip:\+49(\d+)@/0$1/`); err != nil {
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if !reflect.DeepEqual(expRSRField1, rsrField) {
t.Errorf("Expecting: %v, received: %v", expRSRField1, rsrField)
}
// With filter
rulesStr = `~sip_redirected_to:s/sip:\+49(\d+)@/0$1/(086517174963)`
filter, _ := NewRSRFilter("086517174963")
expRSRField2 := &RSRField{Id: "sip_redirected_to", filters: []*RSRFilter{filter},
expRSRField2 := &RSRField{Id: "sip_redirected_to", Rules: rulesStr, filters: []*RSRFilter{filter},
RSRules: []*ReSearchReplace{&ReSearchReplace{SearchRegexp: regexp.MustCompile(`sip:\+49(\d+)@`), ReplaceTemplate: "0$1"}}}
if rsrField, err := NewRSRField(`~sip_redirected_to:s/sip:\+49(\d+)@/0$1/(086517174963)`); err != nil {
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if !reflect.DeepEqual(expRSRField2, rsrField) {
t.Errorf("Expecting: %v, received: %v", expRSRField2, rsrField)
}
// Separator escaped
if rsrField, err := NewRSRField(`~sip_redirected_to:s\/sip:\+49(\d+)@/0$1/`); err == nil {
rulesStr = `~sip_redirected_to:s\/sip:\+49(\d+)@/0$1/`
if rsrField, err := NewRSRField(rulesStr); err == nil {
t.Errorf("Parse error, field rule does not contain correct number of separators, received: %v", rsrField)
}
// One extra separator but escaped
expRSRField3 := &RSRField{Id: "sip_redirected_to",
rulesStr = `~sip_redirected_to:s/sip:\+49(\d+)\/@/0$1/`
expRSRField3 := &RSRField{Id: "sip_redirected_to", Rules: rulesStr,
RSRules: []*ReSearchReplace{&ReSearchReplace{SearchRegexp: regexp.MustCompile(`sip:\+49(\d+)\/@`), ReplaceTemplate: "0$1"}}}
if rsrField, err := NewRSRField(`~sip_redirected_to:s/sip:\+49(\d+)\/@/0$1/`); err != nil {
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if !reflect.DeepEqual(expRSRField3, rsrField) {
t.Errorf("Expecting: %v, received: %v", expRSRField3, rsrField)
@@ -56,9 +60,10 @@ func TestNewRSRField1(t *testing.T) {
}
func TestNewRSRFieldDDz(t *testing.T) {
expectRSRField := &RSRField{Id: "effective_caller_id_number",
rulesStr := `~effective_caller_id_number:s/(\d+)/+$1/`
expectRSRField := &RSRField{Id: "effective_caller_id_number", Rules: rulesStr,
RSRules: []*ReSearchReplace{&ReSearchReplace{SearchRegexp: regexp.MustCompile(`(\d+)`), ReplaceTemplate: "+$1"}}}
if rsrField, err := NewRSRField(`~effective_caller_id_number:s/(\d+)/+$1/`); err != nil {
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rsrField, expectRSRField) {
t.Errorf("Unexpected RSRField received: %v", rsrField)
@@ -66,9 +71,10 @@ func TestNewRSRFieldDDz(t *testing.T) {
}
func TestNewRSRFieldIvo(t *testing.T) {
expectRSRField := &RSRField{Id: "cost_details",
rulesStr := `~cost_details:s/MatchedDestId":".+_(\s\s\s\s\s)"/$1/`
expectRSRField := &RSRField{Id: "cost_details", Rules: rulesStr,
RSRules: []*ReSearchReplace{&ReSearchReplace{SearchRegexp: regexp.MustCompile(`MatchedDestId":".+_(\s\s\s\s\s)"`), ReplaceTemplate: "$1"}}}
if rsrField, err := NewRSRField(`~cost_details:s/MatchedDestId":".+_(\s\s\s\s\s)"/$1/`); err != nil {
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rsrField, expectRSRField) {
t.Errorf("Unexpected RSRField received: %v", rsrField)
@@ -79,10 +85,12 @@ func TestNewRSRFieldIvo(t *testing.T) {
}
func TestConvertPlusNationalAnd00(t *testing.T) {
expectRSRField := &RSRField{Id: "effective_caller_id_number", RSRules: []*ReSearchReplace{
&ReSearchReplace{SearchRegexp: regexp.MustCompile(`\+49(\d+)`), ReplaceTemplate: "0$1"},
&ReSearchReplace{SearchRegexp: regexp.MustCompile(`\+(\d+)`), ReplaceTemplate: "00$1"}}}
rsrField, err := NewRSRField(`~effective_caller_id_number:s/\+49(\d+)/0$1/:s/\+(\d+)/00$1/`)
rulesStr := `~effective_caller_id_number:s/\+49(\d+)/0$1/:s/\+(\d+)/00$1/`
expectRSRField := &RSRField{Id: "effective_caller_id_number", Rules: rulesStr,
RSRules: []*ReSearchReplace{
&ReSearchReplace{SearchRegexp: regexp.MustCompile(`\+49(\d+)`), ReplaceTemplate: "0$1"},
&ReSearchReplace{SearchRegexp: regexp.MustCompile(`\+(\d+)`), ReplaceTemplate: "00$1"}}}
rsrField, err := NewRSRField(rulesStr)
if err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rsrField, expectRSRField) {
@@ -97,16 +105,20 @@ func TestConvertPlusNationalAnd00(t *testing.T) {
}
func TestRSRParseStatic(t *testing.T) {
if rsrField, err := NewRSRField("^static_header::static_value/"); err != nil {
rulesStr := "^static_header::static_value/"
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rsrField, &RSRField{Id: "static_header", staticValue: "static_value"}) {
} else if !reflect.DeepEqual(rsrField, &RSRField{Id: "static_header", Rules: rulesStr,
staticValue: "static_value"}) {
t.Errorf("Unexpected RSRField received: %v", rsrField)
} else if parsed := rsrField.ParseValue("dynamic_value"); parsed != "static_value" {
t.Errorf("Expected: %s, received: %s", "static_value", parsed)
}
if rsrField, err := NewRSRField(`^static_hdrvalue`); err != nil {
rulesStr = `^static_hdrvalue`
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rsrField, &RSRField{Id: "static_hdrvalue", staticValue: "static_hdrvalue"}) {
} else if !reflect.DeepEqual(rsrField, &RSRField{Id: "static_hdrvalue", Rules: rulesStr,
staticValue: "static_hdrvalue"}) {
t.Errorf("Unexpected RSRField received: %v", rsrField)
} else if parsed := rsrField.ParseValue("dynamic_value"); parsed != "static_hdrvalue" {
t.Errorf("Expected: %s, received: %s", "static_hdrvalue", parsed)
@@ -114,9 +126,11 @@ func TestRSRParseStatic(t *testing.T) {
}
func TestConvertDurToSecs(t *testing.T) {
expectRSRField := &RSRField{Id: "9", RSRules: []*ReSearchReplace{
&ReSearchReplace{SearchRegexp: regexp.MustCompile(`^(\d+)$`), ReplaceTemplate: "${1}s"}}}
rsrField, err := NewRSRField(`~9:s/^(\d+)$/${1}s/`)
rulesStr := `~9:s/^(\d+)$/${1}s/`
expectRSRField := &RSRField{Id: "9", Rules: rulesStr,
RSRules: []*ReSearchReplace{
&ReSearchReplace{SearchRegexp: regexp.MustCompile(`^(\d+)$`), ReplaceTemplate: "${1}s"}}}
rsrField, err := NewRSRField(rulesStr)
if err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rsrField, expectRSRField) {
@@ -128,9 +142,11 @@ func TestConvertDurToSecs(t *testing.T) {
}
func TestPrefix164(t *testing.T) {
expectRSRField := &RSRField{Id: "0", RSRules: []*ReSearchReplace{
&ReSearchReplace{SearchRegexp: regexp.MustCompile(`^([1-9]\d+)$`), ReplaceTemplate: "+$1"}}}
rsrField, err := NewRSRField(`~0:s/^([1-9]\d+)$/+$1/`)
rulesStr := `~0:s/^([1-9]\d+)$/+$1/`
expectRSRField := &RSRField{Id: "0", Rules: rulesStr,
RSRules: []*ReSearchReplace{
&ReSearchReplace{SearchRegexp: regexp.MustCompile(`^([1-9]\d+)$`), ReplaceTemplate: "+$1"}}}
rsrField, err := NewRSRField(rulesStr)
if err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rsrField, expectRSRField) {
@@ -166,10 +182,10 @@ func TestParseRSRFields(t *testing.T) {
}
fields := `host,~sip_redirected_to:s/sip:\+49(\d+)@/0$1/,destination`
expectParsedFields := RSRFields{
&RSRField{Id: "host"},
&RSRField{Id: "sip_redirected_to",
&RSRField{Id: "host", Rules: "host"},
&RSRField{Id: "sip_redirected_to", Rules: `~sip_redirected_to:s/sip:\+49(\d+)@/0$1/`,
RSRules: []*ReSearchReplace{&ReSearchReplace{SearchRegexp: regexp.MustCompile(`sip:\+49(\d+)@`), ReplaceTemplate: "0$1"}}},
&RSRField{Id: "destination"}}
&RSRField{Id: "destination", Rules: "destination"}}
if parsedFields, err := ParseRSRFields(fields, FIELDS_SEP); err != nil {
t.Error("Unexpected error: ", err.Error())
} else if !reflect.DeepEqual(parsedFields, expectParsedFields) {
@@ -390,3 +406,43 @@ func TestRSRFiltersPass(t *testing.T) {
t.Error("Passing")
}
}
func TestParseDifferentMethods(t *testing.T) {
rlStr := `~effective_caller_id_number:s/(\d+)/+$1/`
resParseStr, _ := ParseRSRFields(rlStr, INFIELD_SEP)
resParseSlc, _ := ParseRSRFieldsFromSlice([]string{rlStr})
if !reflect.DeepEqual(resParseStr, resParseSlc) {
t.Errorf("Expecting: %+v, received: %+v", resParseStr, resParseSlc)
}
}
func TestIsParsed(t *testing.T) {
rulesStr := `^static_hdrvalue`
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error(err)
} else if !rsrField.IsParsed() {
t.Error("Not parsed")
}
rulesStr = `~effective_caller_id_number:s/(\d+)/+$1/`
if rsrField, err := NewRSRField(rulesStr); err != nil {
t.Error(err)
} else if !rsrField.IsParsed() {
t.Error("Not parsed")
}
rsrField := &RSRField{Rules: rulesStr}
if rsrField.IsParsed() {
t.Error("Is parsed")
}
}
func TestParseRules(t *testing.T) {
rulesStr := `^static_hdrvalue`
rsrField := &RSRField{Rules: rulesStr}
if err := rsrField.ParseRules(); err != nil {
t.Error(err)
}
newRSRFld, _ := NewRSRField(rulesStr)
if reflect.DeepEqual(rsrField, newRSRFld) {
t.Errorf("Expecting: %+v, received: %+v", rsrField, newRSRFld)
}
}