Synched FSCDR with FSCdr object + coeverage tests

This commit is contained in:
porosnicuadrian
2020-11-03 18:14:06 +02:00
committed by Dan Christian Bogos
parent eb39a5ffff
commit 84c8cf038c
4 changed files with 350 additions and 65 deletions

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package agents
import (
"bytes"
"reflect"
"testing"
"time"
@@ -953,15 +954,20 @@ variable_rtp_audio_rtcp_octet_count: 0`
var fsCdrCfg *config.CGRConfig
timezone := config.CgrConfig().GeneralCfg().DefaultTimezone
fsCdrCfg, _ = config.NewDefaultCGRConfig()
fsCdr, _ := engine.NewFSCdr(body, fsCdrCfg)
newReader := bytes.NewReader(body)
fsCdr, err := engine.NewFSCdr(newReader, fsCdrCfg)
if err != nil {
t.Error(err)
}
smGev := engine.NewMapEvent(NewFSEvent(hangUp).AsMapStringInterface(timezone))
sessions.GetSetCGRID(smGev)
smCDR, err := smGev.AsCDR(fsCdrCfg, utils.EmptyString, timezone)
if err != nil {
t.Fatal(err)
}
fsCDR := fsCdr.AsCDR(timezone)
if fsCDR.CGRID != smCDR.CGRID {
if fsCDR, err := fsCdr.AsCDR(timezone); err != nil {
t.Error(err)
} else if fsCDR.CGRID != smCDR.CGRID {
t.Errorf("Expecting: %s, received: %s", fsCDR.CGRID, smCDR.CGRID)
}
}

View File

@@ -17,7 +17,6 @@ package engine
import (
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
@@ -29,10 +28,8 @@ import (
"github.com/cgrates/rpcclient"
)
var cdrServer *CDRServer // Share the server so we can use it in http handlers
// cgrCdrHandler handles CDRs received over HTTP REST
func cgrCdrHandler(w http.ResponseWriter, r *http.Request) {
func (cdrS *CDRServer) cgrCdrHandler(w http.ResponseWriter, r *http.Request) {
cgrCdr, err := NewCgrCdrFromHttpReq(r)
if err != nil {
utils.Logger.Warning(
@@ -40,7 +37,7 @@ func cgrCdrHandler(w http.ResponseWriter, r *http.Request) {
utils.CDRs, r.Form, err.Error()))
return
}
cdr, err := cgrCdr.AsCDR(cdrServer.cgrCfg.GeneralCfg().DefaultTimezone)
cdr, err := cgrCdr.AsCDR(cdrS.cgrCfg.GeneralCfg().DefaultTimezone)
if err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> could not create CDR entry from rawCDR: %+v, err <%s>",
@@ -48,7 +45,7 @@ func cgrCdrHandler(w http.ResponseWriter, r *http.Request) {
return
}
var ignored string
if err := cdrServer.V1ProcessCDR(&CDRWithOpts{CDR: cdr}, &ignored); err != nil {
if err := cdrS.V1ProcessCDR(&CDRWithOpts{CDR: cdr}, &ignored); err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> processing CDR: %s, err: <%s>",
utils.CDRs, cdr, err.Error()))
@@ -56,16 +53,20 @@ func cgrCdrHandler(w http.ResponseWriter, r *http.Request) {
}
// fsCdrHandler will handle CDRs received from FreeSWITCH over HTTP-JSON
func fsCdrHandler(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
fsCdr, err := NewFSCdr(body, cdrServer.cgrCfg)
func (cdrS *CDRServer) fsCdrHandler(w http.ResponseWriter, r *http.Request) {
fsCdr, err := NewFSCdr(r.Body, cdrS.cgrCfg)
r.Body.Close()
if err != nil {
utils.Logger.Err(fmt.Sprintf("<CDRS> Could not create CDR entry: %s", err.Error()))
return
}
cdr := fsCdr.AsCDR(cdrServer.cgrCfg.GeneralCfg().DefaultTimezone)
cdr, err := fsCdr.AsCDR(cdrS.cgrCfg.GeneralCfg().DefaultTimezone)
if err != nil {
utils.Logger.Err(fmt.Sprintf("<CDRS> Could not create AsCDR entry: %s", err.Error()))
return
}
var ignored string
if err := cdrServer.V1ProcessCDR(&CDRWithOpts{CDR: cdr}, &ignored); err != nil {
if err := cdrS.V1ProcessCDR(&CDRWithOpts{CDR: cdr}, &ignored); err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> processing CDR: %s, err: <%s>",
utils.CDRs, cdr, err.Error()))
@@ -115,9 +116,8 @@ func (cdrS *CDRServer) ListenAndServe(stopChan chan struct{}) (err error) {
// RegisterHandlersToServer is called by cgr-engine to register HTTP URL handlers
func (cdrS *CDRServer) RegisterHandlersToServer(server *utils.Server) {
cdrServer = cdrS // Share the server object for handlers
server.RegisterHttpFunc(cdrS.cgrCfg.HTTPCfg().HTTPCDRsURL, cgrCdrHandler)
server.RegisterHttpFunc(cdrS.cgrCfg.HTTPCfg().HTTPFreeswitchCDRsURL, fsCdrHandler)
server.RegisterHttpFunc(cdrS.cgrCfg.HTTPCfg().HTTPCDRsURL, cdrS.cgrCdrHandler)
server.RegisterHttpFunc(cdrS.cgrCfg.HTTPCfg().HTTPFreeswitchCDRsURL, cdrS.fsCdrHandler)
}
// storeSMCost will store a SMCost

View File

@@ -21,6 +21,7 @@ package engine
import (
"encoding/json"
"fmt"
"io"
"reflect"
"strconv"
"strings"
@@ -48,20 +49,20 @@ const (
FsIPv4 = "FreeSWITCH-IPv4"
)
func NewFSCdr(body []byte, cgrCfg *config.CGRConfig) (*FSCdr, error) {
func NewFSCdr(body io.Reader, cgrCfg *config.CGRConfig) (*FSCdr, error) {
fsCdr := &FSCdr{cgrCfg: cgrCfg, vars: make(map[string]string)}
var err error
if err = json.Unmarshal(body, &fsCdr.body); err == nil {
if variables, ok := fsCdr.body[FS_CDR_MAP]; ok {
if variables, ok := variables.(map[string]interface{}); ok {
for k, v := range variables {
fsCdr.vars[k] = v.(string)
}
if err = json.NewDecoder(body).Decode(&fsCdr.body); err != nil {
return nil, err
}
if variables, ok := fsCdr.body[FS_CDR_MAP]; ok {
if variables, ok := variables.(map[string]interface{}); ok {
for k, v := range variables {
fsCdr.vars[k] = v.(string)
}
return fsCdr, nil
}
}
return nil, err
return fsCdr, nil
}
type FSCdr struct {
@@ -88,7 +89,6 @@ func (fsCdr FSCdr) getExtraFields() map[string]string {
if parsed, err := field.Parse(origFieldVal); err == nil {
extraFields[field.Id] = parsed
}
}
return extraFields
}
@@ -136,32 +136,54 @@ func (fsCdr FSCdr) firstDefined(fldNames []string, dfltFld string) (val string)
return fsCdr.searchExtraField(dfltFld, fsCdr.body)
}
func (fsCdr FSCdr) AsCDR(timezone string) *CDR {
storCdr := new(CDR)
storCdr.CGRID = fsCdr.getCGRID()
storCdr.ToR = utils.VOICE
storCdr.OriginID = fsCdr.vars[FS_UUID]
storCdr.OriginHost = utils.FirstNonEmpty(fsCdr.vars[utils.CGROriginHost],
fsCdr.vars[FsIPv4])
storCdr.Source = FS_CDR_SOURCE
storCdr.RequestType = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_REQTYPE],
fsCdr.cgrCfg.GeneralCfg().DefaultReqType)
storCdr.Tenant = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_TENANT],
fsCdr.cgrCfg.GeneralCfg().DefaultTenant)
storCdr.Category = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_CATEGORY],
fsCdr.cgrCfg.GeneralCfg().DefaultCategory)
storCdr.Account = fsCdr.firstDefined([]string{utils.CGR_ACCOUNT, FS_USERNAME},
FsUsername)
storCdr.Subject = fsCdr.firstDefined([]string{utils.CGR_SUBJECT,
utils.CGR_ACCOUNT, FS_USERNAME}, FsUsername)
storCdr.Destination = utils.FirstNonEmpty(fsCdr.vars[utils.CGR_DESTINATION],
fsCdr.vars[FS_CALL_DEST_NR], fsCdr.vars[FS_SIP_REQUSER])
storCdr.SetupTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_SETUP_TIME],
timezone) // Not interested to process errors, should do them if necessary in a previous step
storCdr.AnswerTime, _ = utils.ParseTimeDetectLayout(fsCdr.vars[FS_ANSWER_TIME],
timezone)
storCdr.Usage, _ = utils.ParseDurationWithSecs(fsCdr.vars[FS_DURATION])
storCdr.ExtraFields = fsCdr.getExtraFields()
storCdr.Cost = -1
return storCdr
func (fsCdr FSCdr) AsCDR(timezone string) (storCdr *CDR, err error) {
storCdr = &CDR{
CGRID: fsCdr.getCGRID(),
RunID: fsCdr.vars["cgr_runid"],
OriginHost: utils.FirstNonEmpty(fsCdr.vars[utils.CGROriginHost], fsCdr.vars[FsIPv4]),
Source: FS_CDR_SOURCE,
OriginID: fsCdr.vars[FS_UUID],
ToR: utils.VOICE,
RequestType: utils.FirstNonEmpty(fsCdr.vars[utils.CGR_REQTYPE], fsCdr.cgrCfg.GeneralCfg().DefaultReqType),
Tenant: utils.FirstNonEmpty(fsCdr.vars[utils.CGR_TENANT], fsCdr.cgrCfg.GeneralCfg().DefaultTenant),
Category: utils.FirstNonEmpty(fsCdr.vars[utils.CGR_CATEGORY], fsCdr.cgrCfg.GeneralCfg().DefaultCategory),
Account: fsCdr.firstDefined([]string{utils.CGR_ACCOUNT, FS_USERNAME}, FsUsername),
Subject: fsCdr.firstDefined([]string{utils.CGR_SUBJECT, utils.CGR_ACCOUNT, FS_USERNAME}, FsUsername),
Destination: utils.FirstNonEmpty(fsCdr.vars[utils.CGR_DESTINATION], fsCdr.vars[FS_CALL_DEST_NR], fsCdr.vars[FS_SIP_REQUSER]),
ExtraFields: fsCdr.getExtraFields(),
ExtraInfo: fsCdr.vars["cgr_extrainfo"],
CostSource: fsCdr.vars["cgr_costsource"],
Cost: -1,
}
if orderId, hasIt := fsCdr.vars["cgr_orderid"]; hasIt {
if storCdr.OrderID, err = strconv.ParseInt(orderId, 10, 64); err != nil {
return nil, err
}
}
if setupTime, hasIt := fsCdr.vars[FS_SETUP_TIME]; hasIt {
if storCdr.SetupTime, err = utils.ParseTimeDetectLayout(setupTime, timezone); err != nil {
return nil, err
} // Not interested to process errors, should do them if necessary in a previous step
}
if answerTime, hasIt := fsCdr.vars[FS_ANSWER_TIME]; hasIt {
if storCdr.AnswerTime, err = utils.ParseTimeDetectLayout(answerTime, timezone); err != nil {
return nil, err
}
}
if usage, hasIt := fsCdr.vars[FS_DURATION]; hasIt {
if storCdr.Usage, err = utils.ParseDurationWithSecs(usage); err != nil {
return nil, err
}
}
if partial, hasIt := fsCdr.vars["cgr_partial"]; hasIt {
if storCdr.Partial, err = strconv.ParseBool(partial); err != nil {
return nil, err
}
}
if preRated, hasIt := fsCdr.vars["cgr_prerated"]; hasIt {
if storCdr.PreRated, err = strconv.ParseBool(preRated); err != nil {
return nil, err
}
}
return
}

View File

@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"bytes"
"reflect"
"testing"
"time"
@@ -394,7 +395,8 @@ var fsCdrCfg *config.CGRConfig
func TestFsCdrFirstNonEmpty(t *testing.T) {
fsCdrCfg, _ = config.NewDefaultCGRConfig()
fsCdr, err := NewFSCdr(body, fsCdrCfg)
reader := bytes.NewReader(body)
fsCdr, err := NewFSCdr(reader, fsCdrCfg)
if err != nil {
t.Errorf("Error loading cdr: %v", err)
}
@@ -406,7 +408,8 @@ func TestFsCdrFirstNonEmpty(t *testing.T) {
func TestFsCdrCDRFields(t *testing.T) {
fsCdrCfg.CdrsCfg().ExtraFields = []*utils.RSRField{{Id: "sip_user_agent"}}
fsCdr, err := NewFSCdr(body, fsCdrCfg)
reader := bytes.NewReader(body)
fsCdr, err := NewFSCdr(reader, fsCdrCfg)
if err != nil {
t.Errorf("Error loading cdr: %v", err)
}
@@ -422,13 +425,19 @@ func TestFsCdrCDRFields(t *testing.T) {
AnswerTime: answerTime, Usage: 68 * time.Second,
Cost: -1,
ExtraFields: map[string]string{"sip_user_agent": "Jitsi2.10.5550Linux"}}
if CDR := fsCdr.AsCDR(""); !reflect.DeepEqual(expctCDR, CDR) {
if CDR, err := fsCdr.AsCDR(""); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expctCDR, CDR) {
t.Errorf("Expecting: %+v, received: %+v", expctCDR, CDR)
}
}
func TestFsCdrSearchExtraFieldLast(t *testing.T) {
fsCdr, _ := NewFSCdr(body, fsCdrCfg)
newReader := bytes.NewReader(body)
fsCdr, err := NewFSCdr(newReader, fsCdrCfg)
if err != nil {
t.Error(err)
}
value := fsCdr.searchExtraField("progress_media_time", fsCdr.body)
if value != "1515666347954373" {
t.Error("Error finding extra field: ", value)
@@ -436,7 +445,11 @@ func TestFsCdrSearchExtraFieldLast(t *testing.T) {
}
func TestFsCdrSearchExtraField(t *testing.T) {
fsCdr, _ := NewFSCdr(body, fsCdrCfg)
newReader := bytes.NewReader(body)
fsCdr, err := NewFSCdr(newReader, fsCdrCfg)
if err != nil {
t.Error(err)
}
rsrSt1, _ := utils.NewRSRField("^injected_value")
rsrSt2, _ := utils.NewRSRField("^injected_hdr::injected_value/")
fsCdrCfg.CdrsCfg().ExtraFields = []*utils.RSRField{{Id: "caller_id_name"}, rsrSt1, rsrSt2}
@@ -450,15 +463,21 @@ func TestFsCdrSearchExtraField(t *testing.T) {
}
func TestFsCdrSearchExtraFieldInSlice(t *testing.T) {
fsCdr, _ := NewFSCdr(body, fsCdrCfg)
if value := fsCdr.searchExtraField("floatfld1", map[string]interface{}{"floatfld1": 6.4}); value != "6.4" {
newReader := bytes.NewReader(body)
if fsCdr, err := NewFSCdr(newReader, fsCdrCfg); err != nil {
t.Error(err)
} else if value := fsCdr.searchExtraField("floatfld1", map[string]interface{}{"floatfld1": 6.4}); value != "6.4" {
t.Errorf("Expecting: 6.4, received: %s", value)
}
}
func TestFsCdrSearchReplaceInExtraFields(t *testing.T) {
fsCdrCfg.CdrsCfg().ExtraFields = utils.ParseRSRFieldsMustCompile(`read_codec;~sip_user_agent:s/([A-Za-z]*).+/$1/;write_codec`, utils.INFIELD_SEP)
fsCdr, _ := NewFSCdr(body, fsCdrCfg)
newReader := bytes.NewReader(body)
fsCdr, err := NewFSCdr(newReader, fsCdrCfg)
if err != nil {
t.Error(err)
}
extraFields := fsCdr.getExtraFields()
if len(extraFields) != 3 {
t.Error("Error parsing extra fields: ", extraFields)
@@ -509,7 +528,8 @@ func TestFsCdrDDazRSRExtraFields(t *testing.T) {
} else if !reflect.DeepEqual(expCdrExtra[0], fsCdrCfg.CdrsCfg().ExtraFields[0]) { // Kinda deepEqual bug since without index does not match
t.Errorf("Expecting: %+v, received: %+v", expCdrExtra, fsCdrCfg.CdrsCfg().ExtraFields)
}
fsCdr, err := NewFSCdr(simpleJsonCdr, fsCdrCfg)
newReader := bytes.NewReader(simpleJsonCdr)
fsCdr, err := NewFSCdr(newReader, fsCdrCfg)
if err != nil {
t.Error("Could not parse cdr", err.Error())
}
@@ -520,7 +540,8 @@ func TestFsCdrDDazRSRExtraFields(t *testing.T) {
}
func TestFsCdrFirstDefined(t *testing.T) {
fsCdr, _ := NewFSCdr(body, fsCdrCfg)
newReader := bytes.NewReader(body)
fsCdr, _ := NewFSCdr(newReader, fsCdrCfg)
value := fsCdr.firstDefined([]string{utils.CGR_SUBJECT, utils.CGR_ACCOUNT, FS_USERNAME}, FsUsername)
if value != "1001" {
t.Errorf("Expecting: 1001, received: %s", value)
@@ -530,3 +551,239 @@ func TestFsCdrFirstDefined(t *testing.T) {
t.Errorf("Expecting: 1001, received: %s", value)
}
}
func TestFscdrAsCDR(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
cgrCfg.CdrsCfg().ExtraFields, err = utils.ParseRSRFieldsFromSlice([]string{"PayPalAccount"})
if err != nil {
t.Error(err)
}
fsCdrByte := []byte(` {
"variables": {
"cgr_orderid": "123",
"cgr_partial": "true",
"cgr_prerated": "false"
}
}`)
expectedCdr := &CDR{
OrderID: 123,
ToR: utils.META_VOICE,
Source: FS_CDR_SOURCE, Category: cgrCfg.GeneralCfg().DefaultCategory,
Tenant: cgrCfg.GeneralCfg().DefaultTenant,
RequestType: cgrCfg.GeneralCfg().DefaultReqType,
Partial: true,
PreRated: false,
ExtraFields: map[string]string{
"PayPalAccount": "",
},
Cost: -1,
}
newReader := bytes.NewReader(fsCdrByte)
if fsCdr, err := NewFSCdr(newReader, cgrCfg); err != nil {
t.Error(err)
} else {
expectedCdr.CGRID = fsCdr.getCGRID()
if cdr, err := fsCdr.AsCDR(""); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expectedCdr, cdr) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedCdr), utils.ToJSON(cdr))
}
}
}
func TestFscdrAsCdrOrderId(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
fsCdrByte := []byte(` {
"variables": {
"cgr_orderid": "123s"
}
}`)
expectedErr := "strconv.ParseInt: parsing \"123s\": invalid syntax"
newReader := bytes.NewReader(fsCdrByte)
if fsCdr, err := NewFSCdr(newReader, cgrCfg); err != nil {
t.Error(err)
} else if _, err := fsCdr.AsCDR(""); err == nil || err.Error() != expectedErr {
t.Errorf("Expected %+v \n, received %+v", expectedErr, err)
}
}
func TestFscdrAsCdrSetupTime(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
fsCdrByte := []byte(` {
"variables": {
"start_epoch": "123ss"
}
}`)
expectedErr := "Unsupported time format"
newReader := bytes.NewReader(fsCdrByte)
if fsCdr, err := NewFSCdr(newReader, cgrCfg); err != nil {
t.Error(err)
} else if _, err := fsCdr.AsCDR(""); err == nil || err.Error() != expectedErr {
t.Errorf("Expected %+v \n, received %+v", expectedErr, err)
}
}
func TestFscdrAsCdrAnswerTime(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
fsCdrByte := []byte(` {
"variables": {
"answer_epoch": "123ss"
}
}`)
expectedErr := "Unsupported time format"
newReader := bytes.NewReader(fsCdrByte)
if fsCdr, err := NewFSCdr(newReader, cgrCfg); err != nil {
t.Error(err)
} else if _, err := fsCdr.AsCDR(""); err == nil || err.Error() != expectedErr {
t.Errorf("Expected %+v \n, received %+v", expectedErr, err)
}
}
func TestFscdrAsCdrUsage(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
fsCdrByte := []byte(` {
"variables": {
"billsec": "1ss"
}
}`)
expectedErr := "time: unknown unit \"ss\" in duration \"1ss\""
newReader := bytes.NewReader(fsCdrByte)
if fsCdr, err := NewFSCdr(newReader, cgrCfg); err != nil {
t.Error(err)
} else if _, err := fsCdr.AsCDR(""); err == nil || err.Error() != expectedErr {
t.Errorf("Expected %+v \n, received %+v", expectedErr, err)
}
}
func TestFscdrAsCdrPartial(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
fsCdrByte := []byte(` {
"variables": {
"cgr_partial": "InvalidBoolFormat"
}
}`)
expectedErr := "strconv.ParseBool: parsing \"InvalidBoolFormat\": invalid syntax"
newReader := bytes.NewReader(fsCdrByte)
if fsCdr, err := NewFSCdr(newReader, cgrCfg); err != nil {
t.Error(err)
} else if _, err := fsCdr.AsCDR(""); err == nil || err.Error() != expectedErr {
t.Errorf("Expected %+v \n, received %+v", expectedErr, err)
}
}
func TestFscdrAsCdrPreRated(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
fsCdrByte := []byte(` {
"variables": {
"cgr_prerated": "InvalidBoolFormat"
}
}`)
expectedErr := "strconv.ParseBool: parsing \"InvalidBoolFormat\": invalid syntax"
newReader := bytes.NewReader(fsCdrByte)
if fsCdr, err := NewFSCdr(newReader, cgrCfg); err != nil {
t.Error(err)
} else if _, err := fsCdr.AsCDR(""); err == nil || err.Error() != expectedErr {
t.Errorf("Expected %+v \n, received %+v", expectedErr, err)
}
}
func TestFscdrAsCdrFirstDefined(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
fsCdrByte := []byte(` {
"variables": {
"cgr_account": "randomAccount"
}
}`)
expectedCdr := &CDR{
ToR: utils.META_VOICE,
Source: FS_CDR_SOURCE, Category: cgrCfg.GeneralCfg().DefaultCategory,
Tenant: cgrCfg.GeneralCfg().DefaultTenant,
RequestType: cgrCfg.GeneralCfg().DefaultReqType,
Account: "randomAccount",
Subject: "randomAccount",
ExtraFields: map[string]string{},
Cost: -1,
}
newReader := bytes.NewReader(fsCdrByte)
if fsCdr, err := NewFSCdr(newReader, cgrCfg); err != nil {
t.Error(err)
} else {
expectedCdr.CGRID = fsCdr.getCGRID()
if cdr, err := fsCdr.AsCDR(""); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expectedCdr, cdr) {
t.Errorf("Expected %+v \n, redceived %+v", utils.ToJSON(expectedCdr), utils.ToJSON(cdr))
}
}
}
func TestNewFSCdrDecodeError(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
expectedErr := "EOF"
newReader := bytes.NewReader(nil)
if _, err := NewFSCdr(newReader, cgrCfg); err == nil || err.Error() != expectedErr {
t.Errorf("Expected %+v, received %+v", expectedErr, err)
}
}
func TestSearchExtraFieldDefaultType(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
newMap := map[string]interface{}{
"variables": map[string]string{
"cgr_orderid": "123",
},
}
fsCdr := FSCdr{
cgrCfg: cgrCfg,
body: newMap,
}
fsCdr.searchExtraField(utils.EmptyString, newMap)
}
func TestSearchExtraFieldInterface(t *testing.T) {
cgrCfg, err := config.NewDefaultCGRConfig()
if err != nil {
t.Error(err)
}
newMap := map[string]interface{}{ //There is a slice with no maps
"variables": []interface{}{
2,
"randomValue",
true,
},
}
fsCdr := FSCdr{
cgrCfg: cgrCfg,
body: newMap,
}
fsCdr.searchExtraField(utils.EmptyString, newMap)
}