mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-21 07:08:45 +05:00
Refactoring CDRs to support RSRFields
This commit is contained in:
153
utils/cgrcdr.go
153
utils/cgrcdr.go
@@ -19,10 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -78,7 +75,7 @@ func (cgrCdr CgrCdr) GetDestination() string {
|
||||
}
|
||||
|
||||
func (cgrCdr CgrCdr) GetCategory() string {
|
||||
return cgrCdr[Category]
|
||||
return cgrCdr[CATEGORY]
|
||||
}
|
||||
|
||||
func (cgrCdr CgrCdr) GetTenant() string {
|
||||
@@ -108,133 +105,23 @@ func (cgrCdr CgrCdr) GetDuration() (time.Duration, error) {
|
||||
return ParseDurationWithSecs(cgrCdr[DURATION])
|
||||
}
|
||||
|
||||
// Used in mediation, fieldsMandatory marks whether missing field out of request represents error or can be ignored
|
||||
// If the fields in parameters start with ^ their value is considered instead of dynamically retrieving it from CDR
|
||||
func (cgrCdr CgrCdr) ForkCdr(runId, reqTypeFld, directionFld, tenantFld, torFld, accountFld, subjectFld, destFld, setupTimeFld, answerTimeFld, durationFld string, extraFlds []string, fieldsMandatory bool) (*StoredCdr, error) {
|
||||
if IsSliceMember([]string{runId, reqTypeFld, directionFld, tenantFld, torFld, accountFld, subjectFld, destFld, answerTimeFld, durationFld}, "") {
|
||||
return nil, errors.New(fmt.Sprintf("%s:FieldName", ERR_MANDATORY_IE_MISSING)) // All input field names are mandatory
|
||||
}
|
||||
var err error
|
||||
var hasKey bool
|
||||
var sTimeStr, aTimeStr, durStr string
|
||||
rtCdr := new(StoredCdr)
|
||||
rtCdr.MediationRunId = runId
|
||||
rtCdr.Cost = -1.0 // Default for non-rated CDR
|
||||
if rtCdr.AccId, hasKey = cgrCdr[ACCID]; !hasKey {
|
||||
if fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, ACCID))
|
||||
}
|
||||
}
|
||||
// MetaDefault will automatically be converted to their standard values
|
||||
if reqTypeFld == META_DEFAULT {
|
||||
reqTypeFld = REQTYPE
|
||||
}
|
||||
if directionFld == META_DEFAULT {
|
||||
directionFld = DIRECTION
|
||||
}
|
||||
if tenantFld == META_DEFAULT {
|
||||
tenantFld = TENANT
|
||||
}
|
||||
if torFld == META_DEFAULT {
|
||||
torFld = Category
|
||||
}
|
||||
if accountFld == META_DEFAULT {
|
||||
accountFld = ACCOUNT
|
||||
}
|
||||
if subjectFld == META_DEFAULT {
|
||||
subjectFld = SUBJECT
|
||||
}
|
||||
if destFld == META_DEFAULT {
|
||||
destFld = DESTINATION
|
||||
}
|
||||
if setupTimeFld == META_DEFAULT {
|
||||
setupTimeFld = SETUP_TIME
|
||||
}
|
||||
if answerTimeFld == META_DEFAULT {
|
||||
answerTimeFld = ANSWER_TIME
|
||||
}
|
||||
if durationFld == META_DEFAULT {
|
||||
durationFld = DURATION
|
||||
}
|
||||
if rtCdr.CdrHost, hasKey = cgrCdr[CDRHOST]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, CDRHOST))
|
||||
}
|
||||
if rtCdr.CdrSource, hasKey = cgrCdr[CDRSOURCE]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, CDRSOURCE))
|
||||
}
|
||||
if strings.HasPrefix(reqTypeFld, STATIC_VALUE_PREFIX) { // Values starting with prefix are not dynamically populated
|
||||
rtCdr.ReqType = reqTypeFld[1:]
|
||||
} else if rtCdr.ReqType, hasKey = cgrCdr[reqTypeFld]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, reqTypeFld))
|
||||
}
|
||||
if strings.HasPrefix(directionFld, STATIC_VALUE_PREFIX) {
|
||||
rtCdr.Direction = directionFld[1:]
|
||||
} else if rtCdr.Direction, hasKey = cgrCdr[directionFld]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, directionFld))
|
||||
}
|
||||
if strings.HasPrefix(tenantFld, STATIC_VALUE_PREFIX) {
|
||||
rtCdr.Tenant = tenantFld[1:]
|
||||
} else if rtCdr.Tenant, hasKey = cgrCdr[tenantFld]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, tenantFld))
|
||||
}
|
||||
if strings.HasPrefix(torFld, STATIC_VALUE_PREFIX) {
|
||||
rtCdr.Category = torFld[1:]
|
||||
} else if rtCdr.Category, hasKey = cgrCdr[torFld]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, torFld))
|
||||
}
|
||||
if strings.HasPrefix(accountFld, STATIC_VALUE_PREFIX) {
|
||||
rtCdr.Account = accountFld[1:]
|
||||
} else if rtCdr.Account, hasKey = cgrCdr[accountFld]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, accountFld))
|
||||
}
|
||||
if strings.HasPrefix(subjectFld, STATIC_VALUE_PREFIX) {
|
||||
rtCdr.Subject = subjectFld[1:]
|
||||
} else if rtCdr.Subject, hasKey = cgrCdr[subjectFld]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, subjectFld))
|
||||
}
|
||||
if strings.HasPrefix(destFld, STATIC_VALUE_PREFIX) {
|
||||
rtCdr.Destination = destFld[1:]
|
||||
} else if rtCdr.Destination, hasKey = cgrCdr[destFld]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, destFld))
|
||||
}
|
||||
if sTimeStr, hasKey = cgrCdr[setupTimeFld]; !hasKey && fieldsMandatory && !strings.HasPrefix(setupTimeFld, STATIC_VALUE_PREFIX) {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, setupTimeFld))
|
||||
} else {
|
||||
if strings.HasPrefix(setupTimeFld, STATIC_VALUE_PREFIX) {
|
||||
sTimeStr = setupTimeFld[1:]
|
||||
}
|
||||
if rtCdr.SetupTime, err = ParseTimeDetectLayout(sTimeStr); err != nil && fieldsMandatory {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if aTimeStr, hasKey = cgrCdr[answerTimeFld]; !hasKey && fieldsMandatory && !strings.HasPrefix(answerTimeFld, STATIC_VALUE_PREFIX) {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, answerTimeFld))
|
||||
} else {
|
||||
if strings.HasPrefix(answerTimeFld, STATIC_VALUE_PREFIX) {
|
||||
aTimeStr = answerTimeFld[1:]
|
||||
}
|
||||
if rtCdr.AnswerTime, err = ParseTimeDetectLayout(aTimeStr); err != nil && fieldsMandatory {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if durStr, hasKey = cgrCdr[durationFld]; !hasKey && fieldsMandatory && !strings.HasPrefix(durationFld, STATIC_VALUE_PREFIX) {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, durationFld))
|
||||
} else {
|
||||
if strings.HasPrefix(durationFld, STATIC_VALUE_PREFIX) {
|
||||
durStr = durationFld[1:]
|
||||
}
|
||||
if rtCdr.Duration, err = ParseDurationWithSecs(durStr); err != nil && fieldsMandatory {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
rtCdr.ExtraFields = make(map[string]string, len(extraFlds))
|
||||
for _, fldName := range extraFlds {
|
||||
if fldVal, hasKey := cgrCdr[fldName]; !hasKey && fieldsMandatory {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s", ERR_MANDATORY_IE_MISSING, fldName))
|
||||
} else {
|
||||
rtCdr.ExtraFields[fldName] = fldVal
|
||||
}
|
||||
}
|
||||
rtCdr.CgrId = Sha1(rtCdr.AccId, rtCdr.SetupTime.String())
|
||||
return rtCdr, nil
|
||||
func (cgrCdr CgrCdr) AsStoredCdr() *StoredCdr {
|
||||
storCdr := new(StoredCdr)
|
||||
storCdr.CgrId = cgrCdr.GetCgrId()
|
||||
storCdr.AccId = cgrCdr.GetAccId()
|
||||
storCdr.CdrHost = cgrCdr.GetCdrHost()
|
||||
storCdr.CdrSource = cgrCdr.GetCdrSource()
|
||||
storCdr.ReqType = cgrCdr.GetReqType()
|
||||
storCdr.Direction = cgrCdr.GetDirection()
|
||||
storCdr.Tenant = cgrCdr.GetTenant()
|
||||
storCdr.Category = cgrCdr.GetCategory()
|
||||
storCdr.Account = cgrCdr.GetAccount()
|
||||
storCdr.Subject = cgrCdr.GetSubject()
|
||||
storCdr.Destination = cgrCdr.GetDestination()
|
||||
storCdr.SetupTime, _ = cgrCdr.GetSetupTime() // Not interested to process errors, should do them if necessary in a previous step
|
||||
storCdr.AnswerTime, _ = cgrCdr.GetAnswerTime()
|
||||
storCdr.Duration, _ = cgrCdr.GetDuration()
|
||||
storCdr.ExtraFields = cgrCdr.GetExtraFields()
|
||||
storCdr.Cost = -1
|
||||
return storCdr
|
||||
}
|
||||
|
||||
@@ -28,9 +28,13 @@ import (
|
||||
curl --data "accid=asbfdsaf&cdrhost=192.168.1.1&reqtype=rated&direction=*out&tenant=cgrates.org&tor=call&account=1001&subject=1001&destination=1002&time_answer=1383813746&duration=10&field_extr1=val_extr1&fieldextr2=valextr2" http://ipbxdev:2080/cgr
|
||||
*/
|
||||
|
||||
func TestCgrCdrInterfaces(t *testing.T) {
|
||||
var _ RawCdr = make(CgrCdr)
|
||||
}
|
||||
|
||||
func TestCgrCdrFields(t *testing.T) {
|
||||
cgrCdr := CgrCdr{"accid": "dsafdsaf", "cdrhost": "192.168.1.1", "reqtype": "rated", "direction": "*out", "tenant": "cgrates.org", "tor": "call",
|
||||
"account": "1001", "subject": "1001", "destination": "1002", "setup_time": "2013-11-07T08:42:20Z", "answer_time": "2013-11-07T08:42:26Z", "duration": "10",
|
||||
cgrCdr := CgrCdr{ACCID: "dsafdsaf", CDRHOST: "192.168.1.1", REQTYPE: "rated", DIRECTION: "*out", TENANT: "cgrates.org", CATEGORY: "call",
|
||||
ACCOUNT: "1001", SUBJECT: "1001", DESTINATION: "1002", SETUP_TIME: "2013-11-07T08:42:20Z", ANSWER_TIME: "2013-11-07T08:42:26Z", DURATION: "10",
|
||||
"field_extr1": "val_extr1", "fieldextr2": "valextr2"}
|
||||
setupTime, _ := ParseTimeDetectLayout("2013-11-07T08:42:20Z")
|
||||
if cgrCdr.GetCgrId() != Sha1("dsafdsaf", setupTime.String()) {
|
||||
@@ -85,76 +89,16 @@ func TestCgrCdrFields(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCgrCdrForkCdr(t *testing.T) {
|
||||
sampleCdr1 := &CgrCdr{"accid": "dsafdsaf", "cdrhost": "192.168.1.1", "cdrsource": "source_test", "reqtype": "rated", "direction": "*out", "tenant": "cgrates.org", "tor": "call",
|
||||
"account": "1001", "subject": "1001", "destination": "1002", "setup_time": "2013-11-07T08:42:24Z", "answer_time": "2013-11-07T08:42:26Z", "duration": "10",
|
||||
func TestCgrCdrAsStoredCdr(t *testing.T) {
|
||||
cgrCdr := CgrCdr{ACCID: "dsafdsaf", CDRHOST: "192.168.1.1", CDRSOURCE: "internal_test", REQTYPE: "rated", DIRECTION: "*out", TENANT: "cgrates.org", CATEGORY: "call",
|
||||
ACCOUNT: "1001", SUBJECT: "1001", DESTINATION: "1002", SETUP_TIME: "2013-11-07T08:42:20Z", ANSWER_TIME: "2013-11-07T08:42:26Z", DURATION: "10",
|
||||
"field_extr1": "val_extr1", "fieldextr2": "valextr2"}
|
||||
rtSampleCdrOut, err := sampleCdr1.ForkCdr("sample_run1", "reqtype", "direction", "tenant", "tor", "account", "subject", "destination", "setup_time", "answer_time", "duration",
|
||||
[]string{}, true)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received", err)
|
||||
}
|
||||
setupTime1 := time.Date(2013, 11, 7, 8, 42, 24, 0, time.UTC)
|
||||
expctSplRatedCdr := &StoredCdr{CgrId: Sha1("dsafdsaf", setupTime1.String()), AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "source_test", ReqType: "rated",
|
||||
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: setupTime1, AnswerTime: time.Unix(1383813746, 0).UTC(),
|
||||
Duration: 10000000000, ExtraFields: map[string]string{}, MediationRunId: "sample_run1", Cost: -1}
|
||||
if !reflect.DeepEqual(expctSplRatedCdr, rtSampleCdrOut) {
|
||||
t.Errorf("Expected: %v, received: %v", expctSplRatedCdr, rtSampleCdrOut)
|
||||
}
|
||||
cgrCdr := &CgrCdr{"accid": "dsafdsaf", "cdrhost": "192.168.1.1", "cdrsource": "source_test", "reqtype": "rated", "direction": "*out", "tenant": "cgrates.org", "tor": "call",
|
||||
"account": "1001", "subject": "1001", "destination": "1002", "setup_time": "2013-11-07T08:42:24Z", "answer_time": "2013-11-07T08:42:26Z", "duration": "10",
|
||||
"field_extr1": "val_extr1", "fieldextr2": "valextr2"}
|
||||
rtCdrOut, err := cgrCdr.ForkCdr("wholesale_run", "reqtype", "direction", "tenant", "tor", "account", "subject", "destination", "setup_time", "answer_time", "duration",
|
||||
[]string{"field_extr1", "fieldextr2"}, true)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received", err)
|
||||
}
|
||||
setupTime, _ := ParseTimeDetectLayout("2013-11-07T08:42:24Z")
|
||||
expctRatedCdr := &StoredCdr{CgrId: Sha1("dsafdsaf", setupTime.String()), AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "source_test", ReqType: "rated",
|
||||
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: time.Unix(1383813744, 0).UTC(), AnswerTime: time.Unix(1383813746, 0).UTC(),
|
||||
Duration: 10000000000, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: "wholesale_run", Cost: -1}
|
||||
if !reflect.DeepEqual(rtCdrOut, expctRatedCdr) {
|
||||
t.Errorf("Received: %v, expected: %v", rtCdrOut, expctRatedCdr)
|
||||
}
|
||||
rtCdrOut2, err := cgrCdr.ForkCdr("wholesale_run", "^postpaid", "^*in", "^cgrates.com", "^premium_call", "^first_account", "^first_subject", "destination",
|
||||
"^2013-12-07T08:42:24Z", "^2013-12-07T08:42:26Z", "^12s", []string{"field_extr1", "fieldextr2"}, true)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received", err)
|
||||
}
|
||||
expctRatedCdr2 := &StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "source_test", ReqType: "postpaid",
|
||||
Direction: "*in", Tenant: "cgrates.com", Category: "premium_call", Account: "first_account", Subject: "first_subject", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC),
|
||||
AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), Duration: time.Duration(12) * time.Second,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: "wholesale_run", Cost: -1}
|
||||
if !reflect.DeepEqual(rtCdrOut2, expctRatedCdr2) {
|
||||
t.Errorf("Received: %v, expected: %v", rtCdrOut2, expctRatedCdr2)
|
||||
}
|
||||
_, err = cgrCdr.ForkCdr("wholesale_run", "dummy_header", "direction", "tenant", "tor", "account", "subject", "destination", "setup_time", "answer_time", "duration",
|
||||
[]string{"field_extr1", "fieldextr2"}, true)
|
||||
if err == nil {
|
||||
t.Error("Failed to detect missing header")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCgrCdrForkCdrFromMetaDefaults(t *testing.T) {
|
||||
cgrCdr := &CgrCdr{"accid": "dsafdsaf", "cdrhost": "192.168.1.1", "cdrsource": "source_test", "reqtype": "rated", "direction": "*out", "tenant": "cgrates.org", "tor": "call",
|
||||
"account": "1001", "subject": "1001", "destination": "1002", "setup_time": "2013-11-07T08:42:24Z", "answer_time": "2013-11-07T08:42:26Z", "duration": "10",
|
||||
"field_extr1": "val_extr1", "fieldextr2": "valextr2"}
|
||||
setupTime := time.Date(2013, 11, 7, 8, 42, 24, 0, time.UTC)
|
||||
expctCdr := &StoredCdr{CgrId: Sha1("dsafdsaf", setupTime.String()), AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "source_test", ReqType: "rated",
|
||||
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: setupTime, AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
|
||||
Duration: time.Duration(10) * time.Second,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: "wholesale_run", Cost: -1}
|
||||
cdrOut, err := cgrCdr.ForkCdr("wholesale_run", META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT, META_DEFAULT,
|
||||
META_DEFAULT, META_DEFAULT, META_DEFAULT, []string{"field_extr1", "fieldextr2"}, true)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error received", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expctCdr, cdrOut) {
|
||||
t.Errorf("Expected: %v, received: %v", expctCdr, cdrOut)
|
||||
setupTime, _ := ParseTimeDetectLayout(cgrCdr["setup_time"])
|
||||
expctRtCdr := &StoredCdr{CgrId: Sha1(cgrCdr["accid"], setupTime.String()), AccId: cgrCdr["accid"], CdrHost: cgrCdr["cdrhost"], CdrSource: cgrCdr["cdrsource"], ReqType: cgrCdr["reqtype"],
|
||||
Direction: cgrCdr[DIRECTION], Tenant: cgrCdr["tenant"], Category: cgrCdr[CATEGORY], Account: cgrCdr["account"], Subject: cgrCdr["subject"],
|
||||
Destination: cgrCdr["destination"], SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Duration: time.Duration(10) * time.Second,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: -1}
|
||||
if storedCdr := cgrCdr.AsStoredCdr(); !reflect.DeepEqual(expctRtCdr, storedCdr) {
|
||||
t.Errorf("Expecting %v, received: %v", expctRtCdr, storedCdr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ const (
|
||||
REQTYPE = "reqtype"
|
||||
DIRECTION = "direction"
|
||||
TENANT = "tenant"
|
||||
Category = "tor"
|
||||
CATEGORY = "category"
|
||||
ACCOUNT = "account"
|
||||
SUBJECT = "subject"
|
||||
DESTINATION = "destination"
|
||||
@@ -92,7 +92,7 @@ const (
|
||||
COST = "cost"
|
||||
DEFAULT_RUNID = "default"
|
||||
STATIC_VALUE_PREFIX = "^"
|
||||
CDRE_CSV = "csv"
|
||||
CSV = "csv"
|
||||
CDRE_DRYRUN = "dry_run"
|
||||
INTERNAL = "internal"
|
||||
ZERO_RATING_SUBJECT_PREFIX = "*zero"
|
||||
@@ -104,8 +104,11 @@ const (
|
||||
CONCATENATED_KEY_SEP = ":"
|
||||
META_DEFAULT = "*default"
|
||||
FORKED_CDR = "forked_cdr"
|
||||
UNIT_TEST = "UNIT_TEST"
|
||||
HDR_VAL_SEP = "/"
|
||||
)
|
||||
|
||||
var (
|
||||
CdreCdrFormats = []string{CDRE_CSV, CDRE_DRYRUN, CDRE_FIXED_WIDTH}
|
||||
CdreCdrFormats = []string{CSV, CDRE_DRYRUN, CDRE_FIXED_WIDTH}
|
||||
PrimaryCdrFields = []string{ACCID, CDRHOST, CDRSOURCE, REQTYPE, DIRECTION, TENANT, CATEGORY, ACCOUNT, SUBJECT, DESTINATION, SETUP_TIME, ANSWER_TIME, DURATION}
|
||||
)
|
||||
|
||||
@@ -18,28 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var PrimaryCdrFields []string = []string{ACCID, CDRHOST, CDRSOURCE, REQTYPE, DIRECTION, TENANT, Category, ACCOUNT, SUBJECT, DESTINATION, SETUP_TIME, ANSWER_TIME, DURATION}
|
||||
|
||||
// RawCDR is the type containing all the original CDR fields, needs it as it is for later usage
|
||||
type RawCDR interface {
|
||||
GetCgrId() string
|
||||
GetAccId() string
|
||||
GetCdrHost() string
|
||||
GetCdrSource() string
|
||||
GetDirection() string
|
||||
GetSubject() string
|
||||
GetAccount() string
|
||||
GetDestination() string
|
||||
GetCategory() string
|
||||
GetTenant() string
|
||||
GetReqType() string
|
||||
GetSetupTime() (time.Time, error) // Time when the call was set-up
|
||||
GetAnswerTime() (time.Time, error) // Time when the call was answered
|
||||
GetDuration() (time.Duration, error)
|
||||
GetExtraFields() map[string]string //Stores extra CDR Fields
|
||||
ForkCdr(string, string, string, string, string, string, string, string, string, string, string, []string, bool) (*StoredCdr, error) // Based on fields queried will return a particular instance of RatedCDR
|
||||
// RawCDR is the original CDR received from external sources (eg: FreeSWITCH)
|
||||
type RawCdr interface {
|
||||
AsStoredCdr() *StoredCdr // Convert the inbound Cdr into internally used one, CgrCdr
|
||||
}
|
||||
|
||||
@@ -28,6 +28,15 @@ func NewRSRField(fldStr string) (*RSRField, error) {
|
||||
if len(fldStr) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
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, HDR_VAL_SEP); len(splt) == 2 { // Using | as separator since ':' is often use in date/time fields
|
||||
staticHdr, staticVal = splt[0][1:], splt[1]
|
||||
} 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}, nil
|
||||
}
|
||||
if !strings.HasPrefix(fldStr, REGEXP_PREFIX) {
|
||||
return &RSRField{Id: fldStr}, nil
|
||||
}
|
||||
@@ -53,12 +62,16 @@ func NewRSRField(fldStr string) (*RSRField, error) {
|
||||
}
|
||||
|
||||
type RSRField struct {
|
||||
Id string // Identifier
|
||||
RSRules []*ReSearchReplace // Rules to use when processing field value
|
||||
Id string // Identifier
|
||||
RSRules []*ReSearchReplace // Rules to use when processing field value
|
||||
staticValue string // If defined, enforces parsing always to this value
|
||||
}
|
||||
|
||||
// Parse the field value from a string
|
||||
func (rsrf *RSRField) ParseValue(value string) string {
|
||||
if len(rsrf.staticValue) != 0 { // Enforce parsing of static values
|
||||
return rsrf.staticValue
|
||||
}
|
||||
if len(value) == 0 {
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -80,3 +80,20 @@ func TestConvertPlusNationalAnd00(t *testing.T) {
|
||||
t.Errorf("Expecting: 003186517174963, received: %s", parsedVal)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRSRParseStatic(t *testing.T) {
|
||||
if rsrField, err := NewRSRField("^static_header/static_value"); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rsrField, &RSRField{Id: "static_header", 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 {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rsrField, &RSRField{Id: "static_hdrvalue", 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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,40 +19,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewStoredCdrFromRawCDR(rawcdr RawCDR) (*StoredCdr, error) {
|
||||
var err error
|
||||
strCdr := new(StoredCdr)
|
||||
strCdr.CgrId = rawcdr.GetCgrId()
|
||||
strCdr.AccId = rawcdr.GetAccId()
|
||||
strCdr.CdrHost = rawcdr.GetCdrHost()
|
||||
strCdr.CdrSource = rawcdr.GetCdrSource()
|
||||
strCdr.ReqType = rawcdr.GetReqType()
|
||||
strCdr.Direction = rawcdr.GetDirection()
|
||||
strCdr.Tenant = rawcdr.GetTenant()
|
||||
strCdr.Category = rawcdr.GetCategory()
|
||||
strCdr.Account = rawcdr.GetAccount()
|
||||
strCdr.Subject = rawcdr.GetSubject()
|
||||
strCdr.Destination = rawcdr.GetDestination()
|
||||
if strCdr.SetupTime, err = rawcdr.GetSetupTime(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strCdr.AnswerTime, err = rawcdr.GetAnswerTime(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
strCdr.Duration, _ = rawcdr.GetDuration()
|
||||
strCdr.ExtraFields = rawcdr.GetExtraFields()
|
||||
strCdr.MediationRunId = DEFAULT_RUNID
|
||||
strCdr.Cost = -1
|
||||
return strCdr, nil
|
||||
}
|
||||
|
||||
// Rated CDR as extracted from StorDb. Kinda standard of internal CDR, complies to CDR interface also
|
||||
// Kinda standard of internal CDR, complies to CDR interface also
|
||||
type StoredCdr struct {
|
||||
CgrId string
|
||||
OrderId int64 // Stor order id used as export order id
|
||||
@@ -74,68 +49,6 @@ type StoredCdr struct {
|
||||
Cost float64
|
||||
}
|
||||
|
||||
// Methods maintaining RawCDR interface
|
||||
|
||||
func (storedCdr *StoredCdr) GetCgrId() string {
|
||||
return storedCdr.CgrId
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetAccId() string {
|
||||
return storedCdr.AccId
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetCdrHost() string {
|
||||
return storedCdr.CdrHost
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetCdrSource() string {
|
||||
return storedCdr.CdrSource
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetDirection() string {
|
||||
return storedCdr.Direction
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetSubject() string {
|
||||
return storedCdr.Subject
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetAccount() string {
|
||||
return storedCdr.Account
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetDestination() string {
|
||||
return storedCdr.Destination
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetCategory() string {
|
||||
return storedCdr.Category
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetTenant() string {
|
||||
return storedCdr.Tenant
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetReqType() string {
|
||||
return storedCdr.ReqType
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetSetupTime() (time.Time, error) {
|
||||
return storedCdr.SetupTime, nil
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetAnswerTime() (time.Time, error) {
|
||||
return storedCdr.AnswerTime, nil
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetDuration() (time.Duration, error) {
|
||||
return storedCdr.Duration, nil
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) GetExtraFields() map[string]string {
|
||||
return storedCdr.ExtraFields
|
||||
}
|
||||
|
||||
// Return cost as string, formated with number of decimals configured
|
||||
func (storedCdr *StoredCdr) FormatCost(shiftDecimals, roundDecimals int) string {
|
||||
cost := storedCdr.Cost
|
||||
@@ -145,81 +58,165 @@ func (storedCdr *StoredCdr) FormatCost(shiftDecimals, roundDecimals int) string
|
||||
return strconv.FormatFloat(cost, 'f', roundDecimals, 64)
|
||||
}
|
||||
|
||||
// Converts part of the rated Cdr as httpForm used to post remotely to CDRS
|
||||
func (storedCdr *StoredCdr) AsRawCdrHttpForm() url.Values {
|
||||
// Used to retrieve fields as string, primary fields are const labeled
|
||||
func (storedCdr *StoredCdr) FieldAsString(rsrFld *RSRField) string {
|
||||
switch rsrFld.Id {
|
||||
case CGRID:
|
||||
return rsrFld.ParseValue(storedCdr.CgrId)
|
||||
case ORDERID:
|
||||
return rsrFld.ParseValue(strconv.FormatInt(storedCdr.OrderId, 10))
|
||||
case ACCID:
|
||||
return rsrFld.ParseValue(storedCdr.AccId)
|
||||
case CDRHOST:
|
||||
return rsrFld.ParseValue(storedCdr.CdrHost)
|
||||
case CDRSOURCE:
|
||||
return rsrFld.ParseValue(storedCdr.CdrSource)
|
||||
case REQTYPE:
|
||||
return rsrFld.ParseValue(storedCdr.ReqType)
|
||||
case DIRECTION:
|
||||
return rsrFld.ParseValue(storedCdr.Direction)
|
||||
case TENANT:
|
||||
return rsrFld.ParseValue(storedCdr.Tenant)
|
||||
case CATEGORY:
|
||||
return rsrFld.ParseValue(storedCdr.Category)
|
||||
case ACCOUNT:
|
||||
return rsrFld.ParseValue(storedCdr.Account)
|
||||
case SUBJECT:
|
||||
return rsrFld.ParseValue(storedCdr.Subject)
|
||||
case DESTINATION:
|
||||
return rsrFld.ParseValue(storedCdr.Destination)
|
||||
case SETUP_TIME:
|
||||
return rsrFld.ParseValue(storedCdr.SetupTime.String())
|
||||
case ANSWER_TIME:
|
||||
return rsrFld.ParseValue(storedCdr.AnswerTime.String())
|
||||
case DURATION:
|
||||
return rsrFld.ParseValue(strconv.FormatFloat(storedCdr.Duration.Seconds(), 'f', -1, 64))
|
||||
case MEDI_RUNID:
|
||||
return rsrFld.ParseValue(storedCdr.MediationRunId)
|
||||
case COST:
|
||||
return rsrFld.ParseValue(strconv.FormatFloat(storedCdr.Cost, 'f', -1, 64)) // Recommended to use FormatCost
|
||||
default:
|
||||
return rsrFld.ParseValue(storedCdr.ExtraFields[rsrFld.Id])
|
||||
}
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) AsStoredCdr() *StoredCdr {
|
||||
return storedCdr
|
||||
}
|
||||
|
||||
// Ability to send the CgrCdr remotely to another CDR server
|
||||
func (storedCdr *StoredCdr) AsHttpForm() url.Values {
|
||||
v := url.Values{}
|
||||
for fld, val := range storedCdr.ExtraFields {
|
||||
v.Set(fld, val)
|
||||
}
|
||||
v.Set(ACCID, storedCdr.AccId)
|
||||
v.Set(CDRHOST, storedCdr.CdrHost)
|
||||
v.Set(CDRSOURCE, storedCdr.CdrSource)
|
||||
v.Set(REQTYPE, storedCdr.ReqType)
|
||||
v.Set(DIRECTION, storedCdr.Direction)
|
||||
v.Set(TENANT, storedCdr.Tenant)
|
||||
v.Set(Category, storedCdr.Category)
|
||||
v.Set(CATEGORY, storedCdr.Category)
|
||||
v.Set(ACCOUNT, storedCdr.Account)
|
||||
v.Set(SUBJECT, storedCdr.Subject)
|
||||
v.Set(DESTINATION, storedCdr.Destination)
|
||||
v.Set(SETUP_TIME, storedCdr.SetupTime.String())
|
||||
v.Set(ANSWER_TIME, storedCdr.AnswerTime.String())
|
||||
v.Set(DURATION, strconv.FormatFloat(storedCdr.Duration.Seconds(), 'f', -1, 64))
|
||||
for fld, val := range storedCdr.ExtraFields {
|
||||
v.Set(fld, val)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Used to export fields as string, primary fields are const labeled
|
||||
func (storedCdr *StoredCdr) ExportFieldValue(fldName string) string {
|
||||
switch fldName {
|
||||
case CGRID:
|
||||
return storedCdr.CgrId
|
||||
case ORDERID:
|
||||
return strconv.FormatInt(storedCdr.OrderId, 10)
|
||||
case ACCID:
|
||||
return storedCdr.AccId
|
||||
case CDRHOST:
|
||||
return storedCdr.CdrHost
|
||||
case CDRSOURCE:
|
||||
return storedCdr.CdrSource
|
||||
case REQTYPE:
|
||||
return storedCdr.ReqType
|
||||
case DIRECTION:
|
||||
return storedCdr.Direction
|
||||
case TENANT:
|
||||
return storedCdr.Tenant
|
||||
case Category:
|
||||
return storedCdr.Category
|
||||
case ACCOUNT:
|
||||
return storedCdr.Account
|
||||
case SUBJECT:
|
||||
return storedCdr.Subject
|
||||
case DESTINATION:
|
||||
return storedCdr.Destination
|
||||
case SETUP_TIME:
|
||||
return storedCdr.SetupTime.String()
|
||||
case ANSWER_TIME:
|
||||
return storedCdr.AnswerTime.String()
|
||||
case DURATION:
|
||||
return strconv.FormatFloat(storedCdr.Duration.Seconds(), 'f', -1, 64)
|
||||
case MEDI_RUNID:
|
||||
return storedCdr.MediationRunId
|
||||
case COST:
|
||||
return strconv.FormatFloat(storedCdr.Cost, 'f', -1, 64) // Recommended to use FormatCost
|
||||
default:
|
||||
return storedCdr.ExtraFields[fldName]
|
||||
// Used in mediation, primaryMandatory marks whether missing field out of request represents error or can be ignored
|
||||
func (storedCdr *StoredCdr) ForkCdr(runId string, reqTypeFld, directionFld, tenantFld, categFld, accountFld, subjectFld, destFld, setupTimeFld, answerTimeFld, durationFld *RSRField,
|
||||
extraFlds []*RSRField, primaryMandatory bool) (*StoredCdr, error) {
|
||||
// MetaDefault will automatically be converted to their standard values
|
||||
if reqTypeFld.Id == META_DEFAULT {
|
||||
reqTypeFld.Id = REQTYPE
|
||||
}
|
||||
}
|
||||
|
||||
// Converts to CgrCdr, so we can fork with less code
|
||||
func (storedCdr *StoredCdr) AsCgrCdr() CgrCdr {
|
||||
cgrCdr := make(CgrCdr)
|
||||
for _, fldName := range PrimaryCdrFields {
|
||||
cgrCdr[fldName] = storedCdr.ExportFieldValue(fldName)
|
||||
if directionFld.Id == META_DEFAULT {
|
||||
directionFld.Id = DIRECTION
|
||||
}
|
||||
return cgrCdr
|
||||
}
|
||||
|
||||
func (storedCdr *StoredCdr) ForkCdr(runId, reqTypeFld, directionFld, tenantFld, torFld, accountFld, subjectFld, destFld,
|
||||
setupTimeFld, answerTimeFld, durationFld string, extraFlds []string, fieldsMandatory bool) (*StoredCdr, error) {
|
||||
return storedCdr.AsCgrCdr().ForkCdr(runId, reqTypeFld, directionFld, tenantFld, torFld, accountFld, subjectFld, destFld,
|
||||
setupTimeFld, answerTimeFld, durationFld, extraFlds, fieldsMandatory)
|
||||
if tenantFld.Id == META_DEFAULT {
|
||||
tenantFld.Id = TENANT
|
||||
}
|
||||
if categFld.Id == META_DEFAULT {
|
||||
categFld.Id = CATEGORY
|
||||
}
|
||||
if accountFld.Id == META_DEFAULT {
|
||||
accountFld.Id = ACCOUNT
|
||||
}
|
||||
if subjectFld.Id == META_DEFAULT {
|
||||
subjectFld.Id = SUBJECT
|
||||
}
|
||||
if destFld.Id == META_DEFAULT {
|
||||
destFld.Id = DESTINATION
|
||||
}
|
||||
if setupTimeFld.Id == META_DEFAULT {
|
||||
setupTimeFld.Id = SETUP_TIME
|
||||
}
|
||||
if answerTimeFld.Id == META_DEFAULT {
|
||||
answerTimeFld.Id = ANSWER_TIME
|
||||
}
|
||||
if durationFld.Id == META_DEFAULT {
|
||||
durationFld.Id = DURATION
|
||||
}
|
||||
var err error
|
||||
frkStorCdr := new(StoredCdr)
|
||||
frkStorCdr.CgrId = storedCdr.CgrId
|
||||
frkStorCdr.MediationRunId = runId
|
||||
frkStorCdr.Cost = -1.0 // Default for non-rated CDR
|
||||
frkStorCdr.AccId = storedCdr.AccId
|
||||
frkStorCdr.CdrHost = storedCdr.CdrHost
|
||||
frkStorCdr.CdrSource = storedCdr.CdrSource
|
||||
frkStorCdr.ReqType = storedCdr.FieldAsString(reqTypeFld)
|
||||
if primaryMandatory && len(frkStorCdr.ReqType) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, REQTYPE, reqTypeFld.Id))
|
||||
}
|
||||
frkStorCdr.Direction = storedCdr.FieldAsString(directionFld)
|
||||
if primaryMandatory && len(frkStorCdr.Direction) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, DIRECTION, directionFld.Id))
|
||||
}
|
||||
frkStorCdr.Tenant = storedCdr.FieldAsString(tenantFld)
|
||||
if primaryMandatory && len(frkStorCdr.Tenant) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, TENANT, tenantFld.Id))
|
||||
}
|
||||
frkStorCdr.Category = storedCdr.FieldAsString(categFld)
|
||||
if primaryMandatory && len(frkStorCdr.Category) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, CATEGORY, categFld.Id))
|
||||
}
|
||||
frkStorCdr.Account = storedCdr.FieldAsString(accountFld)
|
||||
if primaryMandatory && len(frkStorCdr.Account) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, ACCOUNT, accountFld.Id))
|
||||
}
|
||||
frkStorCdr.Subject = storedCdr.FieldAsString(subjectFld)
|
||||
if primaryMandatory && len(frkStorCdr.Subject) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, SUBJECT, subjectFld.Id))
|
||||
}
|
||||
frkStorCdr.Destination = storedCdr.FieldAsString(destFld)
|
||||
if primaryMandatory && len(frkStorCdr.Destination) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, DESTINATION, destFld.Id))
|
||||
}
|
||||
sTimeStr := storedCdr.FieldAsString(setupTimeFld)
|
||||
if primaryMandatory && len(sTimeStr) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, SETUP_TIME, setupTimeFld.Id))
|
||||
} else if frkStorCdr.SetupTime, err = ParseTimeDetectLayout(sTimeStr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aTimeStr := storedCdr.FieldAsString(answerTimeFld)
|
||||
if primaryMandatory && len(aTimeStr) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, ANSWER_TIME, answerTimeFld.Id))
|
||||
} else if frkStorCdr.AnswerTime, err = ParseTimeDetectLayout(aTimeStr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
durStr := storedCdr.FieldAsString(durationFld)
|
||||
if primaryMandatory && len(durStr) == 0 {
|
||||
return nil, errors.New(fmt.Sprintf("%s:%s:%s", ERR_MANDATORY_IE_MISSING, DURATION, durationFld.Id))
|
||||
} else if frkStorCdr.Duration, err = ParseDurationWithSecs(durStr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frkStorCdr.ExtraFields = make(map[string]string, len(extraFlds))
|
||||
for _, fld := range extraFlds {
|
||||
frkStorCdr.ExtraFields[fld.Id] = storedCdr.FieldAsString(fld)
|
||||
}
|
||||
return frkStorCdr, nil
|
||||
}
|
||||
|
||||
@@ -25,166 +25,54 @@ import (
|
||||
)
|
||||
|
||||
func TestStoredCdrInterfaces(t *testing.T) {
|
||||
ratedCdr := new(StoredCdr)
|
||||
var _ RawCDR = ratedCdr
|
||||
storedCdr := new(StoredCdr)
|
||||
var _ RawCdr = storedCdr
|
||||
}
|
||||
|
||||
func TestNewStoredCdrFromRawCDR(t *testing.T) {
|
||||
cgrCdr := CgrCdr{"accid": "dsafdsaf", "cdrhost": "192.168.1.1", "cdrsource": "internal_test", "reqtype": "rated", "direction": "*out", "tenant": "cgrates.org", "tor": "call",
|
||||
"account": "1001", "subject": "1001", "destination": "1002", "setup_time": "2013-11-07T08:42:20Z", "answer_time": "2013-11-07T08:42:26Z", "duration": "10",
|
||||
"field_extr1": "val_extr1", "fieldextr2": "valextr2"}
|
||||
setupTime, _ := ParseTimeDetectLayout(cgrCdr["setup_time"])
|
||||
expctRtCdr := &StoredCdr{CgrId: Sha1(cgrCdr["accid"], setupTime.String()), AccId: cgrCdr["accid"], CdrHost: cgrCdr["cdrhost"], CdrSource: cgrCdr["cdrsource"], ReqType: cgrCdr["reqtype"],
|
||||
Direction: cgrCdr["direction"], Tenant: cgrCdr["tenant"], Category: cgrCdr["tor"], Account: cgrCdr["account"], Subject: cgrCdr["subject"],
|
||||
Destination: cgrCdr["destination"], SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Duration: time.Duration(10) * time.Second,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: DEFAULT_RUNID, Cost: -1}
|
||||
if rt, err := NewStoredCdrFromRawCDR(cgrCdr); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(rt, expctRtCdr) {
|
||||
t.Errorf("Received %v, expected: %v", rt, expctRtCdr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoredCdrFields(t *testing.T) {
|
||||
ratedCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Unix(1383813746, 0).String()), AccId: "dsafdsaf", CdrHost: "192.168.1.1", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
|
||||
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Unix(1383813746, 0), AnswerTime: time.Unix(1383813746, 0), Duration: 10,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
if ratedCdr.GetCgrId() != Sha1("dsafdsaf", time.Unix(1383813746, 0).String()) {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetAccId() != "dsafdsaf" {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetCdrHost() != "192.168.1.1" {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetDirection() != "*out" {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetSubject() != "1001" {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetAccount() != "1001" {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetDestination() != "1002" {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetCategory() != "call" {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetTenant() != "cgrates.org" {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
if ratedCdr.GetReqType() != RATED {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
setupTime, _ := ratedCdr.GetSetupTime()
|
||||
expectedSTime, _ := time.Parse(time.RFC3339, "2013-11-07T08:42:26Z")
|
||||
if setupTime.UTC() != expectedSTime {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
answerTime, _ := ratedCdr.GetAnswerTime()
|
||||
expectedATime, _ := time.Parse(time.RFC3339, "2013-11-07T08:42:26Z")
|
||||
if answerTime.UTC() != expectedATime {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
dur, _ := ratedCdr.GetDuration()
|
||||
if dur != 10 {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
extraFields := ratedCdr.GetExtraFields()
|
||||
if len(extraFields) != 2 {
|
||||
t.Error("Error parsing extra fields: ", extraFields)
|
||||
}
|
||||
if extraFields["field_extr1"] != "val_extr1" {
|
||||
t.Error("Error parsing extra fields: ", extraFields)
|
||||
}
|
||||
if ratedCdr.Cost != 1.01 {
|
||||
t.Error("Error parsing cdr: ", ratedCdr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAsRawCdrHttpForm(t *testing.T) {
|
||||
ratedCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
|
||||
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
|
||||
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
cdrForm := ratedCdr.AsRawCdrHttpForm()
|
||||
if cdrForm.Get(ACCID) != ratedCdr.AccId {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.AccId, cdrForm.Get(ACCID))
|
||||
}
|
||||
if cdrForm.Get(CDRHOST) != ratedCdr.CdrHost {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.CdrHost, cdrForm.Get(CDRHOST))
|
||||
}
|
||||
if cdrForm.Get(CDRSOURCE) != ratedCdr.CdrSource {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.CdrSource, cdrForm.Get(CDRSOURCE))
|
||||
}
|
||||
if cdrForm.Get(REQTYPE) != ratedCdr.ReqType {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.ReqType, cdrForm.Get(REQTYPE))
|
||||
}
|
||||
if cdrForm.Get(DIRECTION) != ratedCdr.Direction {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.Direction, cdrForm.Get(DIRECTION))
|
||||
}
|
||||
if cdrForm.Get(TENANT) != ratedCdr.Tenant {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.Tenant, cdrForm.Get(TENANT))
|
||||
}
|
||||
if cdrForm.Get(Category) != ratedCdr.Category {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.Category, cdrForm.Get(Category))
|
||||
}
|
||||
if cdrForm.Get(ACCOUNT) != ratedCdr.Account {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.Account, cdrForm.Get(ACCOUNT))
|
||||
}
|
||||
if cdrForm.Get(SUBJECT) != ratedCdr.Subject {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.Subject, cdrForm.Get(SUBJECT))
|
||||
}
|
||||
if cdrForm.Get(DESTINATION) != ratedCdr.Destination {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.Destination, cdrForm.Get(DESTINATION))
|
||||
}
|
||||
if cdrForm.Get(SETUP_TIME) != "2013-11-07 08:42:20 +0000 UTC" {
|
||||
t.Errorf("Expected: %s, received: %s", "2013-11-07 08:42:26 +0000 UTC", cdrForm.Get(SETUP_TIME))
|
||||
}
|
||||
if cdrForm.Get(ANSWER_TIME) != "2013-11-07 08:42:26 +0000 UTC" {
|
||||
t.Errorf("Expected: %s, received: %s", "2013-11-07 08:42:26 +0000 UTC", cdrForm.Get(ANSWER_TIME))
|
||||
}
|
||||
if cdrForm.Get(DURATION) != "10" {
|
||||
t.Errorf("Expected: %s, received: %s", "10", cdrForm.Get(DURATION))
|
||||
}
|
||||
if cdrForm.Get("field_extr1") != ratedCdr.ExtraFields["field_extr1"] {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.ExtraFields["field_extr1"], cdrForm.Get("field_extr1"))
|
||||
}
|
||||
if cdrForm.Get("fieldextr2") != ratedCdr.ExtraFields["fieldextr2"] {
|
||||
t.Errorf("Expected: %s, received: %s", ratedCdr.ExtraFields["fieldextr2"], cdrForm.Get("fieldextr2"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportFieldValue(t *testing.T) {
|
||||
func TestFieldAsString(t *testing.T) {
|
||||
cdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: "rated", Direction: "*out", Tenant: "cgrates.org",
|
||||
Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: DEFAULT_RUNID,
|
||||
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
if cdr.ExportFieldValue(CGRID) != cdr.CgrId ||
|
||||
cdr.ExportFieldValue(ORDERID) != "123" ||
|
||||
cdr.ExportFieldValue(ACCID) != cdr.AccId ||
|
||||
cdr.ExportFieldValue(CDRHOST) != cdr.CdrHost ||
|
||||
cdr.ExportFieldValue(CDRSOURCE) != cdr.CdrSource ||
|
||||
cdr.ExportFieldValue(REQTYPE) != cdr.ReqType ||
|
||||
cdr.ExportFieldValue(DIRECTION) != cdr.Direction ||
|
||||
cdr.ExportFieldValue(TENANT) != cdr.Tenant ||
|
||||
cdr.ExportFieldValue(Category) != cdr.Category ||
|
||||
cdr.ExportFieldValue(ACCOUNT) != cdr.Account ||
|
||||
cdr.ExportFieldValue(SUBJECT) != cdr.Subject ||
|
||||
cdr.ExportFieldValue(DESTINATION) != cdr.Destination ||
|
||||
cdr.ExportFieldValue(SETUP_TIME) != cdr.SetupTime.String() ||
|
||||
cdr.ExportFieldValue(ANSWER_TIME) != cdr.AnswerTime.String() ||
|
||||
cdr.ExportFieldValue(DURATION) != "10" ||
|
||||
cdr.ExportFieldValue(MEDI_RUNID) != cdr.MediationRunId ||
|
||||
cdr.ExportFieldValue(COST) != "1.01" ||
|
||||
cdr.ExportFieldValue("field_extr1") != cdr.ExtraFields["field_extr1"] ||
|
||||
cdr.ExportFieldValue("fieldextr2") != cdr.ExtraFields["fieldextr2"] ||
|
||||
cdr.ExportFieldValue("dummy_field") != "" {
|
||||
t.Error("Unexpected filed value received")
|
||||
if cdr.FieldAsString(&RSRField{Id: CGRID}) != cdr.CgrId ||
|
||||
cdr.FieldAsString(&RSRField{Id: ORDERID}) != "123" ||
|
||||
cdr.FieldAsString(&RSRField{Id: ACCID}) != cdr.AccId ||
|
||||
cdr.FieldAsString(&RSRField{Id: CDRHOST}) != cdr.CdrHost ||
|
||||
cdr.FieldAsString(&RSRField{Id: CDRSOURCE}) != cdr.CdrSource ||
|
||||
cdr.FieldAsString(&RSRField{Id: REQTYPE}) != cdr.ReqType ||
|
||||
cdr.FieldAsString(&RSRField{Id: DIRECTION}) != cdr.Direction ||
|
||||
cdr.FieldAsString(&RSRField{Id: CATEGORY}) != cdr.Category ||
|
||||
cdr.FieldAsString(&RSRField{Id: ACCOUNT}) != cdr.Account ||
|
||||
cdr.FieldAsString(&RSRField{Id: SUBJECT}) != cdr.Subject ||
|
||||
cdr.FieldAsString(&RSRField{Id: DESTINATION}) != cdr.Destination ||
|
||||
cdr.FieldAsString(&RSRField{Id: SETUP_TIME}) != cdr.SetupTime.String() ||
|
||||
cdr.FieldAsString(&RSRField{Id: ANSWER_TIME}) != cdr.AnswerTime.String() ||
|
||||
cdr.FieldAsString(&RSRField{Id: DURATION}) != "10" ||
|
||||
cdr.FieldAsString(&RSRField{Id: MEDI_RUNID}) != cdr.MediationRunId ||
|
||||
cdr.FieldAsString(&RSRField{Id: COST}) != "1.01" ||
|
||||
cdr.FieldAsString(&RSRField{Id: "field_extr1"}) != cdr.ExtraFields["field_extr1"] ||
|
||||
cdr.FieldAsString(&RSRField{Id: "fieldextr2"}) != cdr.ExtraFields["fieldextr2"] ||
|
||||
cdr.FieldAsString(&RSRField{Id: "dummy_field"}) != "" {
|
||||
t.Error("Unexpected filed value received",
|
||||
cdr.FieldAsString(&RSRField{Id: CGRID}) != cdr.CgrId,
|
||||
cdr.FieldAsString(&RSRField{Id: ORDERID}) != "123",
|
||||
cdr.FieldAsString(&RSRField{Id: ACCID}) != cdr.AccId,
|
||||
cdr.FieldAsString(&RSRField{Id: CDRHOST}) != cdr.CdrHost,
|
||||
cdr.FieldAsString(&RSRField{Id: CDRSOURCE}) != cdr.CdrSource,
|
||||
cdr.FieldAsString(&RSRField{Id: REQTYPE}) != cdr.ReqType,
|
||||
cdr.FieldAsString(&RSRField{Id: DIRECTION}) != cdr.Direction,
|
||||
cdr.FieldAsString(&RSRField{Id: CATEGORY}) != cdr.Category,
|
||||
cdr.FieldAsString(&RSRField{Id: ACCOUNT}) != cdr.Account,
|
||||
cdr.FieldAsString(&RSRField{Id: SUBJECT}) != cdr.Subject,
|
||||
cdr.FieldAsString(&RSRField{Id: DESTINATION}) != cdr.Destination,
|
||||
cdr.FieldAsString(&RSRField{Id: SETUP_TIME}) != cdr.SetupTime.String(),
|
||||
cdr.FieldAsString(&RSRField{Id: ANSWER_TIME}) != cdr.AnswerTime.String(),
|
||||
cdr.FieldAsString(&RSRField{Id: DURATION}) != "10",
|
||||
cdr.FieldAsString(&RSRField{Id: MEDI_RUNID}) != cdr.MediationRunId,
|
||||
cdr.FieldAsString(&RSRField{Id: COST}) != "1.01",
|
||||
cdr.FieldAsString(&RSRField{Id: "field_extr1"}) != cdr.ExtraFields["field_extr1"],
|
||||
cdr.FieldAsString(&RSRField{Id: "fieldextr2"}) != cdr.ExtraFields["fieldextr2"],
|
||||
cdr.FieldAsString(&RSRField{Id: "dummy_field"}) != "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,3 +95,138 @@ func TestFormatCost(t *testing.T) {
|
||||
t.Error("Unexpected format of the cost: ", cdr.FormatCost(2, 3))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoredCdrAsHttpForm(t *testing.T) {
|
||||
storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
|
||||
CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: DEFAULT_RUNID,
|
||||
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
cdrForm := storCdr.AsHttpForm()
|
||||
if cdrForm.Get(ACCID) != "dsafdsaf" {
|
||||
t.Errorf("Expected: %s, received: %s", "dsafdsaf", cdrForm.Get(ACCID))
|
||||
}
|
||||
if cdrForm.Get(CDRHOST) != "192.168.1.1" {
|
||||
t.Errorf("Expected: %s, received: %s", "192.168.1.1", cdrForm.Get(CDRHOST))
|
||||
}
|
||||
if cdrForm.Get(CDRSOURCE) != UNIT_TEST {
|
||||
t.Errorf("Expected: %s, received: %s", UNIT_TEST, cdrForm.Get(CDRSOURCE))
|
||||
}
|
||||
if cdrForm.Get(REQTYPE) != "rated" {
|
||||
t.Errorf("Expected: %s, received: %s", "rated", cdrForm.Get(REQTYPE))
|
||||
}
|
||||
if cdrForm.Get(DIRECTION) != "*out" {
|
||||
t.Errorf("Expected: %s, received: %s", "*out", cdrForm.Get(DIRECTION))
|
||||
}
|
||||
if cdrForm.Get(TENANT) != "cgrates.org" {
|
||||
t.Errorf("Expected: %s, received: %s", "cgrates.org", cdrForm.Get(TENANT))
|
||||
}
|
||||
if cdrForm.Get(CATEGORY) != "call" {
|
||||
t.Errorf("Expected: %s, received: %s", "call", cdrForm.Get(CATEGORY))
|
||||
}
|
||||
if cdrForm.Get(ACCOUNT) != "1001" {
|
||||
t.Errorf("Expected: %s, received: %s", "1001", cdrForm.Get(ACCOUNT))
|
||||
}
|
||||
if cdrForm.Get(SUBJECT) != "1001" {
|
||||
t.Errorf("Expected: %s, received: %s", "1001", cdrForm.Get(SUBJECT))
|
||||
}
|
||||
if cdrForm.Get(DESTINATION) != "1002" {
|
||||
t.Errorf("Expected: %s, received: %s", "1002", cdrForm.Get(DESTINATION))
|
||||
}
|
||||
if cdrForm.Get(SETUP_TIME) != "2013-11-07 08:42:20 +0000 UTC" {
|
||||
t.Errorf("Expected: %s, received: %s", "2013-11-07 08:42:20 +0000 UTC", cdrForm.Get(SETUP_TIME))
|
||||
}
|
||||
if cdrForm.Get(ANSWER_TIME) != "2013-11-07 08:42:26 +0000 UTC" {
|
||||
t.Errorf("Expected: %s, received: %s", "2013-11-07 08:42:26 +0000 UTC", cdrForm.Get(ANSWER_TIME))
|
||||
}
|
||||
if cdrForm.Get(DURATION) != "10" {
|
||||
t.Errorf("Expected: %s, received: %s", "10", cdrForm.Get(DURATION))
|
||||
}
|
||||
if cdrForm.Get("field_extr1") != "val_extr1" {
|
||||
t.Errorf("Expected: %s, received: %s", "val_extr1", cdrForm.Get("field_extr1"))
|
||||
}
|
||||
if cdrForm.Get("fieldextr2") != "valextr2" {
|
||||
t.Errorf("Expected: %s, received: %s", "valextr2", cdrForm.Get("fieldextr2"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoredCdrForkCdr(t *testing.T) {
|
||||
storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), OrderId: 123, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
|
||||
CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: DEFAULT_RUNID,
|
||||
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
rtSampleCdrOut, err := storCdr.ForkCdr("sample_run1", &RSRField{Id: REQTYPE}, &RSRField{Id: DIRECTION}, &RSRField{Id: TENANT}, &RSRField{Id: CATEGORY},
|
||||
&RSRField{Id: ACCOUNT}, &RSRField{Id: SUBJECT}, &RSRField{Id: DESTINATION}, &RSRField{Id: SETUP_TIME}, &RSRField{Id: ANSWER_TIME}, &RSRField{Id: DURATION},
|
||||
[]*RSRField{&RSRField{Id: "field_extr1"}, &RSRField{Id: "field_extr2"}}, true)
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received", err)
|
||||
}
|
||||
expctSplRatedCdr := &StoredCdr{CgrId: storCdr.CgrId, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: "rated",
|
||||
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
|
||||
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "field_extr2": "valextr2"}, MediationRunId: "sample_run1", Cost: -1}
|
||||
if !reflect.DeepEqual(expctSplRatedCdr, rtSampleCdrOut) {
|
||||
t.Errorf("Expected: %v, received: %v", expctSplRatedCdr, rtSampleCdrOut)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoredCdrForkCdrStaticVals(t *testing.T) {
|
||||
storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
|
||||
CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: DEFAULT_RUNID,
|
||||
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
rsrStPostpaid, _ := NewRSRField("^postpaid")
|
||||
rsrStIn, _ := NewRSRField("^*in")
|
||||
rsrStCgr, _ := NewRSRField("^cgrates.com")
|
||||
rsrStPC, _ := NewRSRField("^premium_call")
|
||||
rsrStFA, _ := NewRSRField("^first_account")
|
||||
rsrStFS, _ := NewRSRField("^first_subject")
|
||||
rsrStST, _ := NewRSRField("^2013-12-07T08:42:24Z")
|
||||
rsrStAT, _ := NewRSRField("^2013-12-07T08:42:26Z")
|
||||
rsrStDur, _ := NewRSRField("^12s")
|
||||
rtCdrOut2, err := storCdr.ForkCdr("wholesale_run", rsrStPostpaid, rsrStIn, rsrStCgr, rsrStPC, rsrStFA, rsrStFS, &RSRField{Id: "destination"}, rsrStST, rsrStAT, rsrStDur,
|
||||
[]*RSRField{}, true)
|
||||
|
||||
if err != nil {
|
||||
t.Error("Unexpected error received", err)
|
||||
}
|
||||
expctRatedCdr2 := &StoredCdr{CgrId: storCdr.CgrId, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: "postpaid",
|
||||
Direction: "*in", Tenant: "cgrates.com", Category: "premium_call", Account: "first_account", Subject: "first_subject", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC),
|
||||
AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), Duration: time.Duration(12) * time.Second,
|
||||
ExtraFields: map[string]string{}, MediationRunId: "wholesale_run", Cost: -1}
|
||||
if !reflect.DeepEqual(rtCdrOut2, expctRatedCdr2) {
|
||||
t.Errorf("Received: %v, expected: %v", rtCdrOut2, expctRatedCdr2)
|
||||
}
|
||||
_, err = storCdr.ForkCdr("wholesale_run", &RSRField{Id: "dummy_header"}, &RSRField{Id: "direction"}, &RSRField{Id: "tenant"}, &RSRField{Id: "tor"}, &RSRField{Id: "account"},
|
||||
&RSRField{Id: "subject"}, &RSRField{Id: "destination"}, &RSRField{Id: "setup_time"}, &RSRField{Id: "answer_time"}, &RSRField{Id: "duration"},
|
||||
[]*RSRField{}, true)
|
||||
if err == nil {
|
||||
t.Error("Failed to detect missing header")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoredCdrForkCdrFromMetaDefaults(t *testing.T) {
|
||||
storCdr := StoredCdr{CgrId: Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderId: 123, AccId: "dsafdsaf", CdrHost: "192.168.1.1",
|
||||
CdrSource: UNIT_TEST, ReqType: "rated", Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), MediationRunId: DEFAULT_RUNID,
|
||||
Duration: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01,
|
||||
}
|
||||
expctCdr := &StoredCdr{CgrId: storCdr.CgrId, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: UNIT_TEST, ReqType: "rated",
|
||||
Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002",
|
||||
SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC),
|
||||
Duration: time.Duration(10) * time.Second,
|
||||
ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, MediationRunId: "wholesale_run", Cost: -1}
|
||||
cdrOut, err := storCdr.ForkCdr("wholesale_run", &RSRField{Id: META_DEFAULT}, &RSRField{Id: META_DEFAULT}, &RSRField{Id: META_DEFAULT}, &RSRField{Id: META_DEFAULT},
|
||||
&RSRField{Id: META_DEFAULT}, &RSRField{Id: META_DEFAULT}, &RSRField{Id: META_DEFAULT},
|
||||
&RSRField{Id: META_DEFAULT}, &RSRField{Id: META_DEFAULT}, &RSRField{Id: META_DEFAULT}, []*RSRField{&RSRField{Id: "field_extr1"}, &RSRField{Id: "fieldextr2"}}, true)
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error received", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expctCdr, cdrOut) {
|
||||
t.Errorf("Expected: %v, received: %v", expctCdr, cdrOut)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user