diff --git a/agents/agentreq.go b/agents/agentreq.go index d859e2732..708819ef2 100644 --- a/agents/agentreq.go +++ b/agents/agentreq.go @@ -243,11 +243,9 @@ func (aReq *AgentRequest) ParseField( out, err = utils.Sum(iFaceVals...) } if err != nil && - (!strings.HasPrefix(err.Error(), "Could not find") || - cfgFld.Mandatory) { + !strings.HasPrefix(err.Error(), "Could not find") { return } - err = nil if isString { // format the string additionally with fmtFieldWidth out, err = utils.FmtFieldWidth(cfgFld.Tag, out.(string), cfgFld.Width, cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory) diff --git a/agents/agentreq_test.go b/agents/agentreq_test.go index 410f529bd..1b0d956e2 100644 --- a/agents/agentreq_test.go +++ b/agents/agentreq_test.go @@ -19,13 +19,21 @@ along with this program. If not, see package agents import ( + "bufio" + "bytes" + "net/http" "reflect" + "strings" "testing" "time" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" + "github.com/cgrates/radigo" + "github.com/fiorix/go-diameter/diam" + "github.com/fiorix/go-diameter/diam/avp" + "github.com/fiorix/go-diameter/diam/datatype" ) func TestAgReqAsNavigableMap(t *testing.T) { @@ -155,3 +163,195 @@ func TestAgReqMaxCost(t *testing.T) { t.Errorf("expecting: %+v, received: %+v", eMp, mpOut) } } + +func TestAgReqParseFieldDiameter(t *testing.T) { + //creater diameter message + m := diam.NewRequest(diam.CreditControl, 4, nil) + m.NewAVP("Session-Id", avp.Mbit, 0, datatype.UTF8String("simuhuawei;1449573472;00002")) + m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{ + AVP: []*diam.AVP{ + diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(2)), // Subscription-Id-Type + diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("208708000004")), // Subscription-Id-Data + diam.NewAVP(avp.ValueDigits, avp.Mbit, 0, datatype.Integer64(20000)), + }}) + //create diameterDataProvider + dP := newDADataProvider(m) + data, _ := engine.NewMapStorage() + dm := engine.NewDataManager(data) + cfg, _ := config.NewDefaultCGRConfig() + filterS := engine.NewFilterS(cfg, nil, dm) + //pass the data provider to agent request + agReq := newAgentRequest(dP, nil, nil, nil, "cgrates.org", "", filterS) + + tplFlds := []*config.FCTemplate{ + &config.FCTemplate{Tag: "MandatoryFalse", + FieldId: "MandatoryFalse", Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.MandatoryFalse", true), + Mandatory: false}, + &config.FCTemplate{Tag: "MandatoryTrue", + FieldId: "MandatoryTrue", Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.MandatoryTrue", true), + Mandatory: true}, + } + expected := "" + if out, err := agReq.ParseField(tplFlds[0]); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(out, expected) { + t.Errorf("expecting: <%+v>, received: <%+v>", expected, out) + } + if _, err := agReq.ParseField(tplFlds[1]); err == nil || + err.Error() != "Empty source value for fieldID: " { + t.Error(err) + } +} + +func TestAgReqParseFieldRadius(t *testing.T) { + //creater radius message + pkt := radigo.NewPacket(radigo.AccountingRequest, 1, dictRad, coder, "CGRateS.org") + if err := pkt.AddAVPWithName("User-Name", "flopsy", ""); err != nil { + t.Error(err) + } + if err := pkt.AddAVPWithName("Cisco-NAS-Port", "CGR1", "Cisco"); err != nil { + t.Error(err) + } + //create radiusDataProvider + dP, _ := newRADataProvider(pkt) + data, _ := engine.NewMapStorage() + dm := engine.NewDataManager(data) + cfg, _ := config.NewDefaultCGRConfig() + filterS := engine.NewFilterS(cfg, nil, dm) + //pass the data provider to agent request + agReq := newAgentRequest(dP, nil, nil, nil, "cgrates.org", "", filterS) + tplFlds := []*config.FCTemplate{ + &config.FCTemplate{Tag: "MandatoryFalse", + FieldId: "MandatoryFalse", Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.MandatoryFalse", true), + Mandatory: false}, + &config.FCTemplate{Tag: "MandatoryTrue", + FieldId: "MandatoryTrue", Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.MandatoryTrue", true), + Mandatory: true}, + } + expected := "" + if out, err := agReq.ParseField(tplFlds[0]); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(out, expected) { + t.Errorf("expecting: <%+v>, received: <%+v>", expected, out) + } + if _, err := agReq.ParseField(tplFlds[1]); err == nil || + err.Error() != "Empty source value for fieldID: " { + t.Error(err) + } +} + +func TestAgReqParseFieldHttpUrl(t *testing.T) { + //creater radius message + br := bufio.NewReader(strings.NewReader(`GET /cdr?request_type=MOSMS_CDR×tamp=2008-08-15%2017:49:21&message_date=2008-08-15%2017:49:21&transactionid=100744&CDR_ID=123456&carrierid=1&mcc=222&mnc=10&imsi=235180000000000&msisdn=%2B4977000000000&destination=%2B497700000001&message_status=0&IOT=0&service_id=1 HTTP/1.1 +Host: api.cgrates.org + +`)) + req, err := http.ReadRequest(br) + if err != nil { + t.Error(err) + } + //create radiusDataProvider + dP, _ := newHTTPUrlDP(req) + data, _ := engine.NewMapStorage() + dm := engine.NewDataManager(data) + cfg, _ := config.NewDefaultCGRConfig() + filterS := engine.NewFilterS(cfg, nil, dm) + //pass the data provider to agent request + agReq := newAgentRequest(dP, nil, nil, nil, "cgrates.org", "", filterS) + tplFlds := []*config.FCTemplate{ + &config.FCTemplate{Tag: "MandatoryFalse", + FieldId: "MandatoryFalse", Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.MandatoryFalse", true), + Mandatory: false}, + &config.FCTemplate{Tag: "MandatoryTrue", + FieldId: "MandatoryTrue", Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.MandatoryTrue", true), + Mandatory: true}, + } + expected := "" + if out, err := agReq.ParseField(tplFlds[0]); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(out, expected) { + t.Errorf("expecting: <%+v>, received: <%+v>", expected, out) + } + + if _, err := agReq.ParseField(tplFlds[1]); err == nil || + err.Error() != "Empty source value for fieldID: " { + t.Error(err) + } +} + +func TestAgReqParseFieldHttpXml(t *testing.T) { + //creater radius message + body := ` + 2005-08-26T14:16:42 + 2005-08-26T14:16:56 + 2005-08-26T14:17:34 + My Call Reference + 386 + sampleusername + 1 + Conecto LLC + US$0.21 + yes + no + US$0.13 + 44 + + +441624828505 + Isle of Man + 38 + US$0.0200 + US$0.0140 + US$0.0130 + US$0.0082 + + + +44 7624 494075 + Isle of Man + 37 + US$0.2700 + US$0.1890 + US$0.1880 + US$0.1159 + + +` + req, err := http.NewRequest("POST", "http://localhost:8080/", bytes.NewBuffer([]byte(body))) + if err != nil { + t.Error(err) + } + //create radiusDataProvider + dP, _ := newHTTPXmlDP(req) + data, _ := engine.NewMapStorage() + dm := engine.NewDataManager(data) + cfg, _ := config.NewDefaultCGRConfig() + filterS := engine.NewFilterS(cfg, nil, dm) + //pass the data provider to agent request + agReq := newAgentRequest(dP, nil, nil, nil, "cgrates.org", "", filterS) + tplFlds := []*config.FCTemplate{ + &config.FCTemplate{Tag: "MandatoryFalse", + FieldId: "MandatoryFalse", Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.MandatoryFalse", true), + Mandatory: false}, + &config.FCTemplate{Tag: "MandatoryTrue", + FieldId: "MandatoryTrue", Type: utils.META_COMPOSED, + Value: config.NewRSRParsersMustCompile("~*req.MandatoryTrue", true), + Mandatory: true}, + } + expected := "" + if out, err := agReq.ParseField(tplFlds[0]); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(out, expected) { + t.Errorf("expecting: <%+v>, received: <%+v>", expected, out) + } + if _, err := agReq.ParseField(tplFlds[1]); err == nil || + err.Error() != "Empty source value for fieldID: " { + t.Error(err) + } + +} diff --git a/data/conf/samples/diamagent/dryrun.json b/data/conf/samples/diamagent/dryrun.json index c9302ccc3..927f58ad5 100644 --- a/data/conf/samples/diamagent/dryrun.json +++ b/data/conf/samples/diamagent/dryrun.json @@ -13,7 +13,7 @@ {"tag": "Val2", "field_id": "Val2", "type": "*constant", "value": "2"}, {"tag": "Val3", "field_id": "Val3", "type": "*constant", "value": "3"}, {"tag": "OptionalField", "field_id":"OptionalField", "type":"*composed", - "value":"~*req.Inexistent", "manadatory":false}, + "value":"~*req.Inexistent", "mandatory":false}, {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "~*req.Session-Id", "mandatory": true}, {"tag": "RequestType", "field_id": "RequestType", diff --git a/data/conf/samples/diamsctpagent/dryrun.json b/data/conf/samples/diamsctpagent/dryrun.json index 1cbc8d995..927f58ad5 100755 --- a/data/conf/samples/diamsctpagent/dryrun.json +++ b/data/conf/samples/diamsctpagent/dryrun.json @@ -13,21 +13,32 @@ {"tag": "Val2", "field_id": "Val2", "type": "*constant", "value": "2"}, {"tag": "Val3", "field_id": "Val3", "type": "*constant", "value": "3"}, {"tag": "OptionalField", "field_id":"OptionalField", "type":"*composed", - "value":"~*req.Inexistent", "manadatory":false}, + "value":"~*req.Inexistent", "mandatory":false}, {"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "~*req.Session-Id", "mandatory": true}, - {"tag": "RequestType", "field_id": "RequestType", "type": "*constant", "value": "*prepaid"}, - {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "RequestType", "field_id": "RequestType", + "type": "*constant", "value": "*prepaid"}, + {"tag": "SetupTime", "field_id": "SetupTime", "type": "*composed", + "value": "~*req.Event-Timestamp", "mandatory": true}, + {"tag": "UsedUnits1", "field_id": "UsedUnits1", "type": "*composed", "mandatory": true, + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(1)]"}, + {"tag": "UsedUnits2", "field_id": "UsedUnits2", "type": "*composed", "mandatory": true, + "value": "~*req.Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets[~Rating-Group(2)]"}, + ], "reply_fields":[ {"tag": "CCATemplate", "type": "*template", "value": "*cca"}, {"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "2002"}, {"tag": "RatingGroup", "field_id": "Multiple-Services-Credit-Control.Rating-Group", - "type": "*constant", "value": "65000","new_branch": true}, - {"tag": "RatingGroup", "field_id": "Multiple-Services-Credit-Control.Rating-Group", - "type": "*constant", "value": "100","new_branch": true}, - {"tag": "GrantedUsage", "field_id": "Granted-Service-Unit.CC-Time", "type": "*sum", - "value": "~*cgreq.Val1;~*cgreq.Val2;~*cgreq.Val3"}, + "type": "*constant", "value": "1"}, + {"tag": "CCTotalOctets1", "field_id": "Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets", + "type": "*variable", "value": "~*cgreq.UsedUnits1"}, + {"tag": "RatingGroup", "field_id": "Multiple-Services-Credit-Control.Rating-Group", + "type": "*constant", "value": "2","new_branch": true}, + {"tag": "CCTotalOctets2", "field_id": "Multiple-Services-Credit-Control.Used-Service-Unit.CC-Total-Octets", + "type": "*variable", "value": "~*cgreq.UsedUnits2"}, + {"tag": "GrantedUsage", "field_id": "Granted-Service-Unit.CC-Time", "type": "*sum", + "value": "~*cgreq.Val1;~*cgreq.Val2;~*cgreq.Val3"}, ], }, ],