Completing Diameter DryRun integration test

This commit is contained in:
DanB
2018-10-03 19:43:35 +02:00
parent 08fab20917
commit 56ada587d2
7 changed files with 179 additions and 39 deletions

View File

@@ -46,7 +46,7 @@ var dmtClient *DiameterClient
var rplyTimeout time.Duration
func TestDiamITInitCfg(t *testing.T) {
func TestDiamItInitCfg(t *testing.T) {
daCfgPath = path.Join(*dataDir, "conf", "samples", "diamagent")
// Init config first
var err error
@@ -60,14 +60,14 @@ func TestDiamITInitCfg(t *testing.T) {
}
// Remove data in both rating and accounting db
func TestDiamITResetDataDb(t *testing.T) {
func TestDiamItResetDataDb(t *testing.T) {
if err := engine.InitDataDb(daCfg); err != nil {
t.Fatal(err)
}
}
// Wipe out the cdr database
func TestDiamITResetStorDb(t *testing.T) {
func TestDiamItResetStorDb(t *testing.T) {
if err := engine.InitStorDb(daCfg); err != nil {
t.Fatal(err)
}
@@ -75,14 +75,14 @@ func TestDiamITResetStorDb(t *testing.T) {
/*
// Start CGR Engine
func TestDiamITStartEngine(t *testing.T) {
func TestDiamItStartEngine(t *testing.T) {
if _, err := engine.StopStartEngine(daCfgPath, 4000); err != nil {
t.Fatal(err)
}
}
*/
func TestDiamITConnectDiameterClient(t *testing.T) {
func TestDiamItConnectDiameterClient(t *testing.T) {
dmtClient, err = NewDiameterClient(daCfg.DiameterAgentCfg().Listen, "INTEGRATION_TESTS",
daCfg.DiameterAgentCfg().OriginRealm,
daCfg.DiameterAgentCfg().VendorId, daCfg.DiameterAgentCfg().ProductName,
@@ -93,7 +93,7 @@ func TestDiamITConnectDiameterClient(t *testing.T) {
}
// Connect rpc client to rater
func TestDiamITApierRpcConn(t *testing.T) {
func TestDiamItApierRpcConn(t *testing.T) {
var err error
apierRpc, err = jsonrpc.Dial("tcp", daCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
if err != nil {
@@ -102,7 +102,7 @@ func TestDiamITApierRpcConn(t *testing.T) {
}
// Load the tariff plan, creating accounts and their balances
func TestDiamITTPFromFolder(t *testing.T) {
func TestDiamItTPFromFolder(t *testing.T) {
attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "oldtutorial")}
var loadInst utils.LoadInstance
if err := apierRpc.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &loadInst); err != nil {
@@ -111,7 +111,7 @@ func TestDiamITTPFromFolder(t *testing.T) {
time.Sleep(time.Duration(1000) * time.Millisecond) // Give time for scheduler to execute topups
}
func TestDiamITDryRun(t *testing.T) {
func TestDiamItDryRun(t *testing.T) {
ccr := diam.NewRequest(diam.CreditControl, 4, nil)
ccr.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String("cgrates;1451911932;00082"))
ccr.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity("CGR-DA"))
@@ -120,7 +120,7 @@ func TestDiamITDryRun(t *testing.T) {
ccr.NewAVP(avp.DestinationHost, avp.Mbit, 0, datatype.DiameterIdentity("CGR-DA"))
ccr.NewAVP(avp.UserName, avp.Mbit, 0, datatype.UTF8String("CGR-DA"))
ccr.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4))
ccr.NewAVP(avp.ServiceContextID, avp.Mbit, 0, datatype.UTF8String("TestDiamITDryRun")) // Match specific DryRun profile
ccr.NewAVP(avp.ServiceContextID, avp.Mbit, 0, datatype.UTF8String("TestDiamItDryRun")) // Match specific DryRun profile
ccr.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Enumerated(1))
ccr.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Unsigned32(1))
ccr.NewAVP(avp.EventTimestamp, avp.Mbit, 0, datatype.Time(time.Date(2016, 1, 5, 11, 30, 10, 0, time.UTC)))
@@ -169,15 +169,73 @@ func TestDiamITDryRun(t *testing.T) {
if msg == nil {
t.Fatal("No message returned")
}
avps, err := msg.FindAVPsWithPath([]interface{}{"Result-Code"}, dict.UndefinedVendorID)
if err != nil {
// Result-Code
eVal := "2002"
if avps, err := msg.FindAVPsWithPath([]interface{}{"Result-Code"}, dict.UndefinedVendorID); err != nil {
t.Error(err)
} else if len(avps) == 0 {
t.Error("Missing AVP")
} else if val, err := diamAVPAsString(avps[0]); err != nil {
t.Error(err)
} else if val != eVal {
t.Errorf("expecting: %s, received: <%s>", eVal, val)
}
if len(avps) == 0 {
t.Error("Result-Code")
eVal = "cgrates;1451911932;00082"
if avps, err := msg.FindAVPsWithPath([]interface{}{"Session-Id"}, dict.UndefinedVendorID); err != nil {
t.Error(err)
} else if len(avps) == 0 {
t.Error("Missing AVP")
} else if val, err := diamAVPAsString(avps[0]); err != nil {
t.Error(err)
} else if val != eVal {
t.Errorf("expecting: %s, received: <%s>", eVal, val)
}
eVal := "300"
if val, err := diamAVPAsString(avps[0]); err != nil {
eVal = "CGR-DA"
if avps, err := msg.FindAVPsWithPath([]interface{}{"Origin-Host"}, dict.UndefinedVendorID); err != nil {
t.Error(err)
} else if len(avps) == 0 {
t.Error("Missing AVP")
} else if val, err := diamAVPAsString(avps[0]); err != nil {
t.Error(err)
} else if val != eVal {
t.Errorf("expecting: %s, received: <%s>", eVal, val)
}
eVal = "cgrates.org"
if avps, err := msg.FindAVPsWithPath([]interface{}{"Origin-Realm"}, dict.UndefinedVendorID); err != nil {
t.Error(err)
} else if len(avps) == 0 {
t.Error("Missing AVP")
} else if val, err := diamAVPAsString(avps[0]); err != nil {
t.Error(err)
} else if val != eVal {
t.Errorf("expecting: %s, received: <%s>", eVal, val)
}
eVal = "4"
if avps, err := msg.FindAVPsWithPath([]interface{}{"Auth-Application-Id"}, dict.UndefinedVendorID); err != nil {
t.Error(err)
} else if len(avps) == 0 {
t.Error("Missing AVP")
} else if val, err := diamAVPAsString(avps[0]); err != nil {
t.Error(err)
} else if val != eVal {
t.Errorf("expecting: %s, received: <%s>", eVal, val)
}
eVal = "1"
if avps, err := msg.FindAVPsWithPath([]interface{}{"CC-Request-Type"}, dict.UndefinedVendorID); err != nil {
t.Error(err)
} else if len(avps) == 0 {
t.Error("Missing AVP")
} else if val, err := diamAVPAsString(avps[0]); err != nil {
t.Error(err)
} else if val != eVal {
t.Errorf("expecting: %s, received: <%s>", eVal, val)
}
eVal = "1"
if avps, err := msg.FindAVPsWithPath([]interface{}{"CC-Request-Number"}, dict.UndefinedVendorID); err != nil {
t.Error(err)
} else if len(avps) == 0 {
t.Error("Missing AVP")
} else if val, err := diamAVPAsString(avps[0]); err != nil {
t.Error(err)
} else if val != eVal {
t.Errorf("expecting: %s, received: <%s>", eVal, val)

View File

@@ -147,7 +147,6 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) {
writeOnConn(c, m.Answer(diam.UnableToComply))
return
}
fmt.Printf("After processing successfully the message, have reply: %+v\n", rply)
a := m.Answer(diam.Success)
// write reply into message
for _, val := range rply.Values() {
@@ -179,12 +178,12 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) {
writeOnConn(c, m.Answer(diam.UnableToComply))
return
}
var apnd bool
if itm.Config == nil || !itm.Config.NewBranch {
apnd = true
var newBranch bool
if itm.Config != nil && itm.Config.NewBranch {
newBranch = true
}
if err := messageSetAVPsWithPath(a, itm.Path,
itmStr, apnd, da.cgrCfg.DefaultTimezone); err != nil {
itmStr, newBranch, da.cgrCfg.DefaultTimezone); err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> error: %s setting reply item: %s for message: %s",
utils.DiameterAgent, err.Error(), utils.ToJSON(itm), m))

View File

@@ -194,7 +194,7 @@ func newDiamDataType(typ datatype.TypeID, valStr,
// messageAddAVPsWithPath will dynamically add AVPs into the message
// append: append to the message, on false overwrite if AVP is single or add to group if AVP is Grouped
func messageSetAVPsWithPath(m *diam.Message, pathStr []string,
avpValStr string, appnd bool, tmz string) (err error) {
avpValStr string, newBranch bool, tmz string) (err error) {
if len(pathStr) == 0 {
return errors.New("empty path as AVP filter")
}
@@ -209,11 +209,11 @@ func messageSetAVPsWithPath(m *diam.Message, pathStr []string,
dictAVPs[i] = dictAVP
}
}
if dictAVPs[len(path)-1].Data.Type == diam.GroupedAVPType {
lastAVPIdx := len(path) - 1
if dictAVPs[lastAVPIdx].Data.Type == diam.GroupedAVPType {
return errors.New("last AVP in path cannot be GroupedAVP")
}
var msgAVP *diam.AVP // Keep a reference here towards last AVP
lastAVPIdx := len(path) - 1
for i := lastAVPIdx; i >= 0; i-- {
var typeVal datatype.Type
if i == lastAVPIdx {
@@ -225,7 +225,7 @@ func messageSetAVPsWithPath(m *diam.Message, pathStr []string,
AVP: []*diam.AVP{msgAVP}}
}
newMsgAVP := diam.NewAVP(dictAVPs[i].Code, avp.Mbit, dictAVPs[i].VendorID, typeVal) // FixMe: maybe Mbit with dictionary one
if i == lastAVPIdx-1 && !appnd { // last AVP needs to be appended in group
if i == lastAVPIdx-1 && !newBranch {
avps, err := m.FindAVPsWithPath(path[:lastAVPIdx], dict.UndefinedVendorID)
if err != nil {
return err
@@ -239,7 +239,7 @@ func messageSetAVPsWithPath(m *diam.Message, pathStr []string,
}
msgAVP = newMsgAVP
}
if !appnd { // Not group AVP, replace the previous set one with this one
if !newBranch { // Not group AVP, replace the previous set one with this one
avps, err := m.FindAVPsWithPath(path, dict.UndefinedVendorID)
if err != nil {
return err
@@ -302,11 +302,14 @@ func (dP *diameterDP) FieldAsString(fldPath []string) (data string, err error) {
// FieldAsInterface is part of engine.DataProvider interface
func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err error) {
if data, err = dP.cache.FieldAsInterface(fldPath); err == nil ||
err != utils.ErrNotFound { // item found in cache
return nil, err
if data, err = dP.cache.FieldAsInterface(fldPath); err != nil {
if err != utils.ErrNotFound { // item found in cache
return nil, err
}
err = nil // cancel previous err
} else {
return // data was found in cache
}
err = nil // cancel previous err
// lastPath can contain selector inside
lastPath := fldPath[len(fldPath)-1]
var slctrStr string

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package agents
import (
"reflect"
"testing"
"github.com/fiorix/go-diameter/diam"
@@ -103,3 +104,76 @@ func TestDPFieldAsInterface(t *testing.T) {
t.Errorf("Expecting: %v, received: %v", eOut, out)
}
}
func TestMessageSetAVPsWithPath(t *testing.T) {
eMessage := diam.NewRequest(diam.CreditControl, 4, nil)
eMessage.NewAVP("Session-Id", avp.Mbit, 0,
datatype.UTF8String("simuhuawei;1449573472;00001"))
m := diam.NewMessage(diam.CreditControl, diam.RequestFlag, 4,
eMessage.Header.HopByHopID, eMessage.Header.EndToEndID, nil)
if err := messageSetAVPsWithPath(m,
[]string{"Session-Id"}, "simuhuawei;1449573472;00001",
false, "UTC"); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eMessage, m) {
t.Errorf("Expecting: %+v, received: %+v", eMessage, m)
}
// create same attribute twice
eMessage.NewAVP("Session-Id", avp.Mbit, 0,
datatype.UTF8String("simuhuawei;1449573472;00002"))
if err := messageSetAVPsWithPath(m,
[]string{"Session-Id"}, "simuhuawei;1449573472;00002",
true, "UTC"); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eMessage.AVP, m.AVP) {
t.Errorf("Expecting: %+v, received: %+v", eMessage, m)
}
// overwrite of previous attribute
eMessage = diam.NewRequest(diam.CreditControl, 4, nil)
eMessage.NewAVP("Session-Id", avp.Mbit, 0,
datatype.UTF8String("simuhuawei;1449573472;00001"))
eMessage.NewAVP("Session-Id", avp.Mbit, 0,
datatype.UTF8String("simuhuawei;1449573472;00003"))
if err := messageSetAVPsWithPath(m,
[]string{"Session-Id"}, "simuhuawei;1449573472;00003",
false, "UTC"); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eMessage.AVP, m.AVP) {
t.Errorf("Expecting: %+v, received: %+v", eMessage, m)
}
// adding a groupped AVP
eMessage.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{
AVP: []*diam.AVP{
diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Enumerated(0)),
diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.UTF8String("1001")),
}})
if err := messageSetAVPsWithPath(m,
[]string{"Subscription-Id", "Subscription-Id-Type"}, "0",
false, "UTC"); err != nil {
t.Error(err)
}
if err := messageSetAVPsWithPath(m,
[]string{"Subscription-Id", "Subscription-Id-Data"}, "1001",
false, "UTC"); err != nil {
t.Error(err)
} else if len(eMessage.AVP) != len(m.AVP) {
t.Errorf("Expecting: %+v, received: %+v", eMessage, m)
}
eMessage.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{
AVP: []*diam.AVP{
diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Enumerated(1)),
diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.UTF8String("1002")),
}})
if err := messageSetAVPsWithPath(m,
[]string{"Subscription-Id", "Subscription-Id-Type"}, "1",
true, "UTC"); err != nil {
t.Error(err)
}
if err := messageSetAVPsWithPath(m,
[]string{"Subscription-Id", "Subscription-Id-Data"}, "1002",
false, "UTC"); err != nil {
t.Error(err)
} else if len(eMessage.AVP) != len(m.AVP) {
t.Errorf("Expecting: %+v, received: %+v", eMessage, m)
}
}

View File

@@ -62,11 +62,14 @@ func (hU *httpUrlDP) FieldAsInterface(fldPath []string) (data interface{}, err e
if len(fldPath) != 1 {
return nil, utils.ErrNotFound
}
if data, err = hU.cache.FieldAsInterface(fldPath); err == nil ||
err != utils.ErrNotFound { // item found in cache
return
if data, err = hU.cache.FieldAsInterface(fldPath); err != nil {
if err != utils.ErrNotFound { // item found in cache
return
}
err = nil // cancel previous err
} else {
return // data found in cache
}
err = nil // cancel previous err
data = hU.req.FormValue(fldPath[0])
hU.cache.Set(fldPath, data, false)
return

View File

@@ -158,11 +158,14 @@ func (pk *radiusDP) FieldAsInterface(fldPath []string) (data interface{}, err er
if len(fldPath) != 1 {
return nil, utils.ErrNotFound
}
if data, err = pk.cache.FieldAsInterface(fldPath); err == nil ||
err != utils.ErrNotFound { // item found in cache
return
if data, err = pk.cache.FieldAsInterface(fldPath); err != nil {
if err != utils.ErrNotFound { // item found in cache
return
}
err = nil // cancel previous err
} else {
return // data found in cache
}
err = nil // cancel previous err
if len(pk.req.AttributesWithName(fldPath[0], "")) != 0 {
data = pk.req.AttributesWithName(fldPath[0], "")[0].GetStringValue()
}

View File

@@ -5,7 +5,7 @@
{
"id": "dryrun1",
"filters": ["*string:*vars.*cmd:CCR", "*string:*req.Service-Context-Id:TestDiamITDryRun"],
"filters": ["*string:*vars.*cmd:CCR", "*string:*req.Service-Context-Id:TestDiamItDryRun"],
"flags": ["*dryrun"],
"request_fields":[
{"tag": "TOR", "field_id": "ToR", "type": "*constant", "value": "*sms"},
@@ -16,7 +16,7 @@
],
"reply_fields":[
{"tag": "CCATemplate", "type": "*template", "value": "*cca"},
{"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "300"},
{"tag": "ResultCode", "field_id": "Result-Code", "type": "*constant", "value": "2002"},
],
},
],