mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Merged template parsing functions
This commit is contained in:
committed by
Dan Christian Bogos
parent
d63418f260
commit
1db592ea8d
@@ -20,11 +20,8 @@ package agents
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
@@ -321,164 +318,21 @@ func (ar *AgentRequest) Remove(fullPath *utils.FullPath) error {
|
||||
// ParseField outputs the value based on the template item
|
||||
func (ar *AgentRequest) ParseField(
|
||||
cfgFld *config.FCTemplate) (out interface{}, err error) {
|
||||
var isString bool
|
||||
switch cfgFld.Type {
|
||||
default:
|
||||
return utils.EmptyString, fmt.Errorf("unsupported type: <%s>", cfgFld.Type)
|
||||
case utils.MetaNone:
|
||||
return
|
||||
tmpType := cfgFld.Type
|
||||
switch tmpType {
|
||||
case utils.MetaFiller:
|
||||
out, err = cfgFld.Value.ParseValue(utils.EmptyString)
|
||||
cfgFld.Padding = utils.MetaRight
|
||||
isString = true
|
||||
case utils.MetaConstant:
|
||||
out, err = cfgFld.Value.ParseValue(utils.EmptyString)
|
||||
isString = true
|
||||
case utils.MetaRemoteHost:
|
||||
out = ar.RemoteHost().String()
|
||||
isString = true
|
||||
case utils.MetaVariable, utils.MetaComposed, utils.MetaGroup:
|
||||
out, err = cfgFld.Value.ParseDataProvider(ar)
|
||||
isString = true
|
||||
case utils.MetaUsageDifference:
|
||||
if len(cfgFld.Value) != 2 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(cfgFld.Value), utils.MetaUsageDifference)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = cfgFld.Value[0].ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = cfgFld.Value[1].ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var tEnd time.Time
|
||||
if tEnd, err = utils.ParseTimeDetectLayout(strVal1, ar.Timezone); err != nil {
|
||||
return
|
||||
}
|
||||
var tStart time.Time
|
||||
if tStart, err = utils.ParseTimeDetectLayout(strVal2, ar.Timezone); err != nil {
|
||||
return
|
||||
}
|
||||
out = tEnd.Sub(tStart).String()
|
||||
isString = true
|
||||
case utils.MetaCCUsage:
|
||||
if len(cfgFld.Value) != 3 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(cfgFld.Value), utils.MetaCCUsage)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = cfgFld.Value[0].ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var reqNr int64
|
||||
if reqNr, err = strconv.ParseInt(strVal1, 10, 64); err != nil {
|
||||
err = fmt.Errorf("invalid requestNumber <%s> to %s",
|
||||
strVal1, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = cfgFld.Value[1].ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var usedCCTime time.Duration
|
||||
if usedCCTime, err = utils.ParseDurationWithNanosecs(strVal2); err != nil {
|
||||
err = fmt.Errorf("invalid usedCCTime <%s> to %s",
|
||||
strVal2, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
var strVal3 string
|
||||
if strVal3, err = cfgFld.Value[2].ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var debitItvl time.Duration
|
||||
if debitItvl, err = utils.ParseDurationWithNanosecs(strVal3); err != nil {
|
||||
err = fmt.Errorf("invalid debitInterval <%s> to %s",
|
||||
strVal3, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
if reqNr--; reqNr < 0 { // terminate will be ignored (init request should always be 0)
|
||||
reqNr = 0
|
||||
}
|
||||
return usedCCTime + time.Duration(debitItvl.Nanoseconds()*reqNr), nil
|
||||
case utils.MetaSum:
|
||||
var iFaceVals []interface{}
|
||||
if iFaceVals, err = cfgFld.Value.GetIfaceFromValues(ar); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Sum(iFaceVals...)
|
||||
case utils.MetaDifference:
|
||||
var iFaceVals []interface{}
|
||||
if iFaceVals, err = cfgFld.Value.GetIfaceFromValues(ar); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Difference(iFaceVals...)
|
||||
case utils.MetaMultiply:
|
||||
var iFaceVals []interface{}
|
||||
if iFaceVals, err = cfgFld.Value.GetIfaceFromValues(ar); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Multiply(iFaceVals...)
|
||||
case utils.MetaDivide:
|
||||
var iFaceVals []interface{}
|
||||
if iFaceVals, err = cfgFld.Value.GetIfaceFromValues(ar); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Divide(iFaceVals...)
|
||||
case utils.MetaValueExponent:
|
||||
if len(cfgFld.Value) != 2 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(cfgFld.Value), utils.MetaValueExponent)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = cfgFld.Value[0].ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var val float64
|
||||
if val, err = strconv.ParseFloat(strVal1, 64); err != nil {
|
||||
err = fmt.Errorf("invalid value <%s> to %s",
|
||||
strVal1, utils.MetaValueExponent)
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = cfgFld.Value[1].ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var exp int
|
||||
if exp, err = strconv.Atoi(strVal2); err != nil {
|
||||
return
|
||||
}
|
||||
out = strconv.FormatFloat(utils.Round(val*math.Pow10(exp),
|
||||
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.MetaRoundingMiddle), 'f', -1, 64)
|
||||
case utils.MetaUnixTimestamp:
|
||||
var val string
|
||||
if val, err = cfgFld.Value.ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var t1 time.Time
|
||||
if t1, err = utils.ParseTimeDetectLayout(val, cfgFld.Timezone); err != nil {
|
||||
return
|
||||
}
|
||||
out = strconv.Itoa(int(t1.Unix()))
|
||||
case utils.MetaDateTime: // Convert the requested field value into datetime with layout
|
||||
var val string
|
||||
if val, err = cfgFld.Value.ParseDataProvider(ar); err != nil {
|
||||
return
|
||||
}
|
||||
var dtFld time.Time
|
||||
dtFld, err = utils.ParseTimeDetectLayout(val, utils.FirstNonEmpty(cfgFld.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out = dtFld.Format(cfgFld.Layout)
|
||||
tmpType = utils.MetaConstant
|
||||
case utils.MetaGroup:
|
||||
tmpType = utils.MetaVariable
|
||||
}
|
||||
out, err = engine.ParseAttribute(ar, tmpType, cfgFld.Path, cfgFld.Value, config.CgrConfig().GeneralCfg().RoundingDecimals, utils.FirstNonEmpty(cfgFld.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), cfgFld.Layout, config.CgrConfig().GeneralCfg().RSRSep)
|
||||
|
||||
if err != nil &&
|
||||
!strings.HasPrefix(err.Error(), "Could not find") {
|
||||
return
|
||||
}
|
||||
if isString { // format the string additionally with fmtFieldWidth
|
||||
if utils.StringTmplType.Has(tmpType) { // format the string additionally with fmtFieldWidth
|
||||
out, err = utils.FmtFieldWidth(cfgFld.Tag, out.(string), cfgFld.Width,
|
||||
cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory)
|
||||
}
|
||||
|
||||
@@ -219,168 +219,12 @@ func (alS *AttributeService) processEvent(tnt string, args *AttrArgsProcessEvent
|
||||
continue
|
||||
}
|
||||
}
|
||||
var substitute string
|
||||
switch attribute.Type {
|
||||
case utils.MetaConstant:
|
||||
substitute, err = attribute.Value.ParseValue(utils.EmptyString)
|
||||
case utils.MetaVariable, utils.MetaComposed:
|
||||
substitute, err = attribute.Value.ParseDataProvider(dynDP)
|
||||
case utils.MetaUsageDifference:
|
||||
if len(attribute.Value) != 2 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s>", utils.ToJSON(attribute.Value))
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = attribute.Value[0].ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = attribute.Value[1].ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var tEnd time.Time
|
||||
if tEnd, err = utils.ParseTimeDetectLayout(strVal1, utils.EmptyString); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var tStart time.Time
|
||||
if tStart, err = utils.ParseTimeDetectLayout(strVal2, utils.EmptyString); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = tEnd.Sub(tStart).String()
|
||||
case utils.MetaSum:
|
||||
var ifaceVals []interface{}
|
||||
if ifaceVals, err = attribute.Value.GetIfaceFromValues(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var ifaceSum interface{}
|
||||
if ifaceSum, err = utils.Sum(ifaceVals...); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = utils.IfaceAsString(ifaceSum)
|
||||
case utils.MetaDifference:
|
||||
var ifaceVals []interface{}
|
||||
if ifaceVals, err = attribute.Value.GetIfaceFromValues(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var ifaceSum interface{}
|
||||
if ifaceSum, err = utils.Difference(ifaceVals...); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = utils.IfaceAsString(ifaceSum)
|
||||
case utils.MetaMultiply:
|
||||
var ifaceVals []interface{}
|
||||
if ifaceVals, err = attribute.Value.GetIfaceFromValues(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var ifaceSum interface{}
|
||||
if ifaceSum, err = utils.Multiply(ifaceVals...); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = utils.IfaceAsString(ifaceSum)
|
||||
case utils.MetaDivide:
|
||||
var ifaceVals []interface{}
|
||||
if ifaceVals, err = attribute.Value.GetIfaceFromValues(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var ifaceSum interface{}
|
||||
if ifaceSum, err = utils.Divide(ifaceVals...); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = utils.IfaceAsString(ifaceSum)
|
||||
case utils.MetaValueExponent:
|
||||
if len(attribute.Value) != 2 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(attribute.Value), utils.MetaValueExponent)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = attribute.Value[0].ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var val float64
|
||||
if val, err = strconv.ParseFloat(strVal1, 64); err != nil {
|
||||
return nil, fmt.Errorf("invalid value <%s> to %s",
|
||||
strVal1, utils.MetaValueExponent)
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = attribute.Value[1].ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var exp int
|
||||
if exp, err = strconv.Atoi(strVal2); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = strconv.FormatFloat(utils.Round(val*math.Pow10(exp),
|
||||
alS.cgrcfg.GeneralCfg().RoundingDecimals, utils.MetaRoundingMiddle), 'f', -1, 64)
|
||||
case utils.MetaUnixTimestamp:
|
||||
var val string
|
||||
if val, err = attribute.Value.ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var t time.Time
|
||||
if t, err = utils.ParseTimeDetectLayout(val, alS.cgrcfg.GeneralCfg().DefaultTimezone); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = strconv.Itoa(int(t.Unix()))
|
||||
case utils.MetaPrefix:
|
||||
var pathRsr config.RSRParsers
|
||||
pathRsr, err = config.NewRSRParsers(utils.DynamicDataPrefix+attribute.Path, alS.cgrcfg.GeneralCfg().RSRSep)
|
||||
if err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var pathVal string
|
||||
if pathVal, err = pathRsr.ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var val string
|
||||
if val, err = attribute.Value.ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = val + pathVal
|
||||
case utils.MetaSuffix:
|
||||
var pathRsr config.RSRParsers
|
||||
pathRsr, err = config.NewRSRParsers(utils.DynamicDataPrefix+attribute.Path, alS.cgrcfg.GeneralCfg().RSRSep)
|
||||
if err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var pathVal string
|
||||
if pathVal, err = pathRsr.ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
var val string
|
||||
if val, err = attribute.Value.ParseDataProvider(dynDP); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute = pathVal + val
|
||||
default: // backwards compatible in case that Type is empty
|
||||
substitute, err = attribute.Value.ParseDataProvider(dynDP)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
var out interface{}
|
||||
if out, err = ParseAttribute(dynDP, utils.FirstNonEmpty(attribute.Type, utils.MetaVariable), utils.DynamicDataPrefix+attribute.Path, attribute.Value, alS.cgrcfg.GeneralCfg().RoundingDecimals, alS.cgrcfg.GeneralCfg().DefaultTimezone, time.RFC3339, alS.cgrcfg.GeneralCfg().RSRSep); err != nil {
|
||||
rply = nil
|
||||
return
|
||||
}
|
||||
substitute := utils.IfaceAsString(out)
|
||||
//add only once the Path in AlteredFields
|
||||
if !utils.IsSliceMember(rply.AlteredFields, attribute.Path) {
|
||||
rply.AlteredFields = append(rply.AlteredFields, attribute.Path)
|
||||
@@ -517,3 +361,180 @@ func (alS *AttributeService) V1ProcessEvent(args *AttrArgsProcessEvent,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ParseAttribute(dp utils.DataProvider, attrType, path string, value config.RSRParsers, roundingDec int, timeZone, layout, rsrSep string) (
|
||||
out interface{}, err error) {
|
||||
switch attrType {
|
||||
case utils.MetaNone:
|
||||
return
|
||||
case utils.MetaConstant:
|
||||
out, err = value.ParseValue(utils.EmptyString)
|
||||
case utils.MetaVariable, utils.MetaComposed:
|
||||
out, err = value.ParseDataProvider(dp)
|
||||
case utils.MetaUsageDifference:
|
||||
if len(value) != 2 {
|
||||
return "", fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(value), utils.MetaUsageDifference)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = value[0].ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = value[1].ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var tEnd time.Time
|
||||
if tEnd, err = utils.ParseTimeDetectLayout(strVal1, utils.EmptyString); err != nil {
|
||||
return
|
||||
}
|
||||
var tStart time.Time
|
||||
if tStart, err = utils.ParseTimeDetectLayout(strVal2, utils.EmptyString); err != nil {
|
||||
return
|
||||
}
|
||||
out = tEnd.Sub(tStart).String()
|
||||
case utils.MetaSum:
|
||||
var ifaceVals []interface{}
|
||||
if ifaceVals, err = value.GetIfaceFromValues(dp); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Sum(ifaceVals...)
|
||||
case utils.MetaDifference:
|
||||
var ifaceVals []interface{}
|
||||
if ifaceVals, err = value.GetIfaceFromValues(dp); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Difference(timeZone, ifaceVals...)
|
||||
case utils.MetaMultiply:
|
||||
var ifaceVals []interface{}
|
||||
if ifaceVals, err = value.GetIfaceFromValues(dp); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Multiply(ifaceVals...)
|
||||
case utils.MetaDivide:
|
||||
var ifaceVals []interface{}
|
||||
if ifaceVals, err = value.GetIfaceFromValues(dp); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Divide(ifaceVals...)
|
||||
case utils.MetaValueExponent:
|
||||
if len(value) != 2 {
|
||||
return "", fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(value), utils.MetaValueExponent)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = value[0].ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var val float64
|
||||
if val, err = strconv.ParseFloat(strVal1, 64); err != nil {
|
||||
return "", fmt.Errorf("invalid value <%s> to %s",
|
||||
strVal1, utils.MetaValueExponent)
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = value[1].ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var exp int
|
||||
if exp, err = strconv.Atoi(strVal2); err != nil {
|
||||
return
|
||||
}
|
||||
out = strconv.FormatFloat(utils.Round(val*math.Pow10(exp),
|
||||
roundingDec, utils.MetaRoundingMiddle), 'f', -1, 64)
|
||||
case utils.MetaUnixTimestamp:
|
||||
var val string
|
||||
if val, err = value.ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var t time.Time
|
||||
if t, err = utils.ParseTimeDetectLayout(val, timeZone); err != nil {
|
||||
return
|
||||
}
|
||||
out = strconv.Itoa(int(t.Unix()))
|
||||
case utils.MetaDateTime: // Convert the requested field value into datetime with layout
|
||||
var val string
|
||||
if val, err = value.ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var dtFld time.Time
|
||||
dtFld, err = utils.ParseTimeDetectLayout(val, timeZone)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out = dtFld.Format(layout)
|
||||
case utils.MetaPrefix:
|
||||
var pathRsr config.RSRParsers
|
||||
pathRsr, err = config.NewRSRParsers(path, rsrSep)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var pathVal string
|
||||
if pathVal, err = pathRsr.ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var val string
|
||||
if val, err = value.ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
out = val + pathVal
|
||||
case utils.MetaSuffix:
|
||||
var pathRsr config.RSRParsers
|
||||
pathRsr, err = config.NewRSRParsers(path, rsrSep)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var pathVal string
|
||||
if pathVal, err = pathRsr.ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var val string
|
||||
if val, err = value.ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
out = pathVal + val
|
||||
case utils.MetaRemoteHost:
|
||||
out = dp.RemoteHost().String()
|
||||
case utils.MetaCCUsage:
|
||||
if len(value) != 3 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(value), utils.MetaCCUsage)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = value[0].ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var reqNr int64
|
||||
if reqNr, err = strconv.ParseInt(strVal1, 10, 64); err != nil {
|
||||
err = fmt.Errorf("invalid requestNumber <%s> to %s",
|
||||
strVal1, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = value[1].ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var usedCCTime time.Duration
|
||||
if usedCCTime, err = utils.ParseDurationWithNanosecs(strVal2); err != nil {
|
||||
err = fmt.Errorf("invalid usedCCTime <%s> to %s",
|
||||
strVal2, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
var strVal3 string
|
||||
if strVal3, err = value[2].ParseDataProvider(dp); err != nil {
|
||||
return
|
||||
}
|
||||
var debitItvl time.Duration
|
||||
if debitItvl, err = utils.ParseDurationWithNanosecs(strVal3); err != nil {
|
||||
err = fmt.Errorf("invalid debitInterval <%s> to %s",
|
||||
strVal3, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
if reqNr--; reqNr < 0 { // terminate will be ignored (init request should always be 0)
|
||||
reqNr = 0
|
||||
}
|
||||
return usedCCTime + time.Duration(debitItvl.Nanoseconds()*reqNr), nil
|
||||
default:
|
||||
return utils.EmptyString, fmt.Errorf("unsupported type: <%s>", attrType)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -20,11 +20,8 @@ package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
@@ -191,158 +188,8 @@ func (eeR *EventRequest) SetAsSlice(fullPath *utils.FullPath, val *utils.DataLea
|
||||
// ParseField outputs the value based on the template item
|
||||
func (eeR *EventRequest) ParseField(
|
||||
cfgFld *config.FCTemplate) (out interface{}, err error) {
|
||||
var isString bool
|
||||
switch cfgFld.Type {
|
||||
default:
|
||||
return utils.EmptyString, fmt.Errorf("unsupported type: <%s>", cfgFld.Type)
|
||||
case utils.MetaNone:
|
||||
return
|
||||
case utils.MetaFiller:
|
||||
out, err = cfgFld.Value.ParseValue(utils.EmptyString)
|
||||
cfgFld.Padding = utils.MetaRight
|
||||
isString = true
|
||||
case utils.MetaConstant:
|
||||
out, err = cfgFld.Value.ParseValue(utils.EmptyString)
|
||||
isString = true
|
||||
case utils.MetaRemoteHost:
|
||||
out = eeR.RemoteHost().String()
|
||||
isString = true
|
||||
case utils.MetaVariable, utils.MetaComposed, utils.MetaGroup:
|
||||
out, err = cfgFld.Value.ParseDataProvider(eeR)
|
||||
isString = true
|
||||
case utils.MetaUsageDifference:
|
||||
if len(cfgFld.Value) != 2 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(cfgFld.Value), utils.MetaUsageDifference)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = cfgFld.Value[0].ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = cfgFld.Value[1].ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var tEnd time.Time
|
||||
if tEnd, err = utils.ParseTimeDetectLayout(strVal1, eeR.Timezone); err != nil {
|
||||
return
|
||||
}
|
||||
var tStart time.Time
|
||||
if tStart, err = utils.ParseTimeDetectLayout(strVal2, eeR.Timezone); err != nil {
|
||||
return
|
||||
}
|
||||
out = tEnd.Sub(tStart).String()
|
||||
isString = true
|
||||
case utils.MetaCCUsage:
|
||||
if len(cfgFld.Value) != 3 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(cfgFld.Value), utils.MetaCCUsage)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = cfgFld.Value[0].ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var reqNr int64
|
||||
if reqNr, err = strconv.ParseInt(strVal1, 10, 64); err != nil {
|
||||
err = fmt.Errorf("invalid requestNumber <%s> to %s",
|
||||
strVal1, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = cfgFld.Value[1].ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var usedCCTime time.Duration
|
||||
if usedCCTime, err = utils.ParseDurationWithNanosecs(strVal2); err != nil {
|
||||
err = fmt.Errorf("invalid usedCCTime <%s> to %s",
|
||||
strVal2, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
var strVal3 string
|
||||
if strVal3, err = cfgFld.Value[2].ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var debitItvl time.Duration
|
||||
if debitItvl, err = utils.ParseDurationWithNanosecs(strVal3); err != nil {
|
||||
err = fmt.Errorf("invalid debitInterval <%s> to %s",
|
||||
strVal3, utils.MetaCCUsage)
|
||||
return
|
||||
}
|
||||
|
||||
if reqNr--; reqNr < 0 { // terminate will be ignored (init request should always be 0)
|
||||
reqNr = 0
|
||||
}
|
||||
return usedCCTime + time.Duration(debitItvl.Nanoseconds()*reqNr), nil
|
||||
case utils.MetaSum:
|
||||
var iFaceVals []interface{}
|
||||
if iFaceVals, err = cfgFld.Value.GetIfaceFromValues(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Sum(iFaceVals...)
|
||||
case utils.MetaDifference:
|
||||
var iFaceVals []interface{}
|
||||
if iFaceVals, err = cfgFld.Value.GetIfaceFromValues(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Difference(iFaceVals...)
|
||||
case utils.MetaMultiply:
|
||||
var iFaceVals []interface{}
|
||||
if iFaceVals, err = cfgFld.Value.GetIfaceFromValues(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Multiply(iFaceVals...)
|
||||
case utils.MetaDivide:
|
||||
var iFaceVals []interface{}
|
||||
if iFaceVals, err = cfgFld.Value.GetIfaceFromValues(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
out, err = utils.Divide(iFaceVals...)
|
||||
case utils.MetaValueExponent:
|
||||
if len(cfgFld.Value) != 2 {
|
||||
return nil, fmt.Errorf("invalid arguments <%s> to %s",
|
||||
utils.ToJSON(cfgFld.Value), utils.MetaValueExponent)
|
||||
}
|
||||
var strVal1 string
|
||||
if strVal1, err = cfgFld.Value[0].ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var val float64
|
||||
if val, err = strconv.ParseFloat(strVal1, 64); err != nil {
|
||||
err = fmt.Errorf("invalid value <%s> to %s",
|
||||
strVal1, utils.MetaValueExponent)
|
||||
return
|
||||
}
|
||||
var strVal2 string
|
||||
if strVal2, err = cfgFld.Value[1].ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var exp int
|
||||
if exp, err = strconv.Atoi(strVal2); err != nil {
|
||||
return
|
||||
}
|
||||
out = strconv.FormatFloat(utils.Round(val*math.Pow10(exp),
|
||||
config.CgrConfig().GeneralCfg().RoundingDecimals, utils.MetaRoundingMiddle), 'f', -1, 64)
|
||||
case utils.MetaUnixTimestamp:
|
||||
var val string
|
||||
if val, err = cfgFld.Value.ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var t1 time.Time
|
||||
if t1, err = utils.ParseTimeDetectLayout(val, cfgFld.Timezone); err != nil {
|
||||
return
|
||||
}
|
||||
out = strconv.Itoa(int(t1.Unix()))
|
||||
case utils.MetaDateTime: // Convert the requested field value into datetime with layout
|
||||
var val string
|
||||
if val, err = cfgFld.Value.ParseDataProvider(eeR); err != nil {
|
||||
return
|
||||
}
|
||||
var dtFld time.Time
|
||||
dtFld, err = utils.ParseTimeDetectLayout(val, utils.FirstNonEmpty(cfgFld.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out = dtFld.Format(cfgFld.Layout)
|
||||
tmpType := cfgFld.Type
|
||||
switch tmpType {
|
||||
case utils.MetaMaskedDestination:
|
||||
//check if we have destination in the event
|
||||
var dst string
|
||||
@@ -355,14 +202,20 @@ func (eeR *EventRequest) ParseField(
|
||||
CachedDestHasPrefix(cfgFld.MaskDestID, dst) {
|
||||
out = utils.MaskSuffix(dst, cfgFld.MaskLen)
|
||||
}
|
||||
|
||||
return
|
||||
case utils.MetaFiller:
|
||||
cfgFld.Padding = utils.MetaRight
|
||||
tmpType = utils.MetaConstant
|
||||
case utils.MetaGroup:
|
||||
tmpType = utils.MetaVariable
|
||||
}
|
||||
out, err = ParseAttribute(eeR, tmpType, cfgFld.Path, cfgFld.Value, config.CgrConfig().GeneralCfg().RoundingDecimals, utils.FirstNonEmpty(cfgFld.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), cfgFld.Layout, config.CgrConfig().GeneralCfg().RSRSep)
|
||||
|
||||
if err != nil &&
|
||||
!strings.HasPrefix(err.Error(), "Could not find") {
|
||||
return
|
||||
}
|
||||
if isString { // format the string additionally with fmtFieldWidth
|
||||
if utils.StringTmplType.Has(tmpType) { // format the string additionally with fmtFieldWidth
|
||||
out, err = utils.FmtFieldWidth(cfgFld.Tag, out.(string), cfgFld.Width,
|
||||
cfgFld.Strip, cfgFld.Padding, cfgFld.Mandatory)
|
||||
}
|
||||
|
||||
@@ -2660,6 +2660,17 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// StringTmplType a string set used, by agentRequest and eventRequest to determine if the returned template type is string
|
||||
var StringTmplType = StringSet{
|
||||
MetaConstant: struct{}{},
|
||||
MetaRemoteHost: struct{}{},
|
||||
MetaVariable: struct{}{},
|
||||
MetaComposed: struct{}{},
|
||||
MetaUsageDifference: struct{}{},
|
||||
MetaPrefix: struct{}{},
|
||||
MetaSuffix: struct{}{},
|
||||
}
|
||||
|
||||
// Time duration suffix
|
||||
const (
|
||||
NsSuffix = "ns"
|
||||
|
||||
@@ -550,107 +550,126 @@ func Sum(items ...interface{}) (sum interface{}, err error) {
|
||||
|
||||
switch dt := items[0].(type) {
|
||||
case time.Duration:
|
||||
sum = dt
|
||||
s := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsDuration(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
sum = sum.(time.Duration) + itmVal
|
||||
s += itmVal
|
||||
}
|
||||
}
|
||||
sum = s
|
||||
case time.Time:
|
||||
sum = dt
|
||||
s := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsDuration(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
sum = sum.(time.Time).Add(itmVal)
|
||||
s = s.Add(itmVal)
|
||||
}
|
||||
}
|
||||
sum = s
|
||||
case float64:
|
||||
sum = dt
|
||||
s := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsFloat64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
sum = sum.(float64) + itmVal
|
||||
s += itmVal
|
||||
}
|
||||
}
|
||||
sum = s
|
||||
case int64:
|
||||
sum = dt
|
||||
s := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsInt64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
sum = sum.(int64) + itmVal
|
||||
s += itmVal
|
||||
}
|
||||
}
|
||||
sum = s
|
||||
case int:
|
||||
sum = int64(dt)
|
||||
s := int64(dt)
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsInt64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
sum = sum.(int64) + itmVal
|
||||
s += itmVal
|
||||
}
|
||||
}
|
||||
sum = s
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Difference attempts to sum multiple items
|
||||
// returns the result or error if not comparable
|
||||
func Difference(items ...interface{}) (diff interface{}, err error) {
|
||||
func Difference(tm string, items ...interface{}) (diff interface{}, err error) {
|
||||
//we need at least 2 items to diff them
|
||||
if len(items) < 2 {
|
||||
return nil, ErrNotEnoughParameters
|
||||
}
|
||||
switch dt := items[0].(type) {
|
||||
case time.Duration:
|
||||
diff = dt
|
||||
d := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsDuration(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
diff = diff.(time.Duration) - itmVal
|
||||
d -= itmVal
|
||||
}
|
||||
}
|
||||
diff = d
|
||||
case time.Time:
|
||||
diff = dt
|
||||
for _, item := range items[1:] {
|
||||
d := dt
|
||||
for i, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsTime(item, tm); err == nil {
|
||||
diff = d.Sub(itmVal)
|
||||
if len(items) == i+1 {
|
||||
return diff, nil
|
||||
}
|
||||
items[i] = diff
|
||||
return Difference(tm, items[i:]...)
|
||||
}
|
||||
|
||||
if itmVal, err := IfaceAsDuration(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
diff = diff.(time.Time).Add(-itmVal)
|
||||
d = d.Add(-itmVal)
|
||||
}
|
||||
}
|
||||
diff = d
|
||||
case float64:
|
||||
diff = dt
|
||||
d := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsFloat64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
diff = diff.(float64) - itmVal
|
||||
d -= itmVal
|
||||
}
|
||||
}
|
||||
diff = d
|
||||
case int64:
|
||||
diff = dt
|
||||
d := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsInt64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
diff = diff.(int64) - itmVal
|
||||
d -= itmVal
|
||||
}
|
||||
}
|
||||
diff = d
|
||||
case int:
|
||||
diff = int64(dt)
|
||||
d := int64(dt)
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsInt64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
diff = diff.(int64) - itmVal
|
||||
d -= itmVal
|
||||
}
|
||||
}
|
||||
diff = d
|
||||
default: // unsupported comparison
|
||||
return nil, fmt.Errorf("unsupported type")
|
||||
}
|
||||
@@ -666,32 +685,35 @@ func Multiply(items ...interface{}) (mlt interface{}, err error) {
|
||||
}
|
||||
switch dt := items[0].(type) {
|
||||
case float64:
|
||||
mlt = dt
|
||||
m := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsFloat64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
mlt = mlt.(float64) * itmVal
|
||||
m *= itmVal
|
||||
}
|
||||
}
|
||||
mlt = m
|
||||
case int64:
|
||||
mlt = dt
|
||||
m := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsInt64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
mlt = mlt.(int64) * itmVal
|
||||
m *= itmVal
|
||||
}
|
||||
}
|
||||
mlt = m
|
||||
case int:
|
||||
mlt = int64(dt)
|
||||
m := int64(dt)
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsInt64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
mlt = mlt.(int64) * itmVal
|
||||
m *= itmVal
|
||||
}
|
||||
}
|
||||
mlt = m
|
||||
default: // unsupported comparison
|
||||
return nil, fmt.Errorf("unsupported type")
|
||||
}
|
||||
@@ -700,39 +722,42 @@ func Multiply(items ...interface{}) (mlt interface{}, err error) {
|
||||
|
||||
// Divide attempts to divide multiple items
|
||||
// returns the result or error if not comparable
|
||||
func Divide(items ...interface{}) (mlt interface{}, err error) {
|
||||
func Divide(items ...interface{}) (div interface{}, err error) {
|
||||
//we need at least 2 items to diff them
|
||||
if len(items) < 2 {
|
||||
return nil, ErrNotEnoughParameters
|
||||
}
|
||||
switch dt := items[0].(type) {
|
||||
case float64:
|
||||
mlt = dt
|
||||
d := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsFloat64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
mlt = mlt.(float64) / itmVal
|
||||
d /= itmVal
|
||||
}
|
||||
}
|
||||
div = d
|
||||
case int64:
|
||||
mlt = dt
|
||||
d := dt
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsInt64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
mlt = mlt.(int64) / itmVal
|
||||
d /= itmVal
|
||||
}
|
||||
}
|
||||
div = d
|
||||
case int:
|
||||
mlt = int64(dt)
|
||||
d := int64(dt)
|
||||
for _, item := range items[1:] {
|
||||
if itmVal, err := IfaceAsInt64(item); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
mlt = mlt.(int64) / itmVal
|
||||
d /= itmVal
|
||||
}
|
||||
}
|
||||
div = d
|
||||
default: // unsupported comparison
|
||||
return nil, fmt.Errorf("unsupported type")
|
||||
}
|
||||
|
||||
@@ -573,49 +573,49 @@ func TestGetUniformType(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDifference(t *testing.T) {
|
||||
if _, err := Difference(10); err == nil || err != ErrNotEnoughParameters {
|
||||
if _, err := Difference("", 10); err == nil || err != ErrNotEnoughParameters {
|
||||
t.Error(err)
|
||||
}
|
||||
if _, err := Difference(10, 1.2, false); err == nil || err.Error() != "cannot convert field: 1.2 to int" {
|
||||
if _, err := Difference("", 10, 1.2, false); err == nil || err.Error() != "cannot convert field: 1.2 to int" {
|
||||
t.Error(err)
|
||||
}
|
||||
if diff, err := Difference(12, 1, 2, 3); err != nil {
|
||||
if diff, err := Difference("", 12, 1, 2, 3); err != nil {
|
||||
t.Error(err)
|
||||
} else if diff != int64(6) {
|
||||
t.Errorf("Expecting: 6, received: %+v", diff)
|
||||
}
|
||||
if diff, err := Difference(8.0, 4.0, 2.0, -1.0); err != nil {
|
||||
if diff, err := Difference("", 8.0, 4.0, 2.0, -1.0); err != nil {
|
||||
t.Error(err)
|
||||
} else if diff != 3.0 {
|
||||
t.Errorf("Expecting: 3.0, received: %+v", diff)
|
||||
}
|
||||
|
||||
if diff, err := Difference(8.0, 4, 2.0, -1.0); err != nil {
|
||||
if diff, err := Difference("", 8.0, 4, 2.0, -1.0); err != nil {
|
||||
t.Error(err)
|
||||
} else if diff != 3.0 {
|
||||
t.Errorf("Expecting: 3.0, received: %+v", diff)
|
||||
}
|
||||
if diff, err := Difference(10*time.Second, time.Second, 2*time.Second,
|
||||
if diff, err := Difference("", 10*time.Second, time.Second, 2*time.Second,
|
||||
4*time.Millisecond); err != nil {
|
||||
t.Error(err)
|
||||
} else if diff != 6*time.Second+996*time.Millisecond {
|
||||
t.Errorf("Expecting: 6.996ms, received: %+v", diff)
|
||||
}
|
||||
if diff, err := Difference(2*time.Second,
|
||||
if diff, err := Difference("", 2*time.Second,
|
||||
10*time.Millisecond); err != nil {
|
||||
t.Error(err)
|
||||
} else if diff != time.Second+990*time.Millisecond {
|
||||
t.Errorf("Expecting: 1.99s, received: %+v", diff)
|
||||
}
|
||||
|
||||
if diff, err := Difference(time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC),
|
||||
if diff, err := Difference("", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC),
|
||||
10*time.Second); err != nil {
|
||||
t.Error(err)
|
||||
} else if diff != time.Date(2009, 11, 10, 22, 59, 50, 0, time.UTC) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", time.Date(2009, 11, 10, 22, 59, 50, 0, time.UTC), diff)
|
||||
}
|
||||
|
||||
if diff, err := Difference(time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC),
|
||||
if diff, err := Difference("", time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC),
|
||||
10*time.Second, 10000000000); err != nil {
|
||||
t.Error(err)
|
||||
} else if diff != time.Date(2009, 11, 10, 22, 59, 40, 0, time.UTC) {
|
||||
@@ -1405,7 +1405,7 @@ func TestReflectDifferenceTimeDurationError(t *testing.T) {
|
||||
var test2Var bool
|
||||
testVar = 25354
|
||||
test2Var = true
|
||||
_, err := Difference(testVar, test2Var)
|
||||
_, err := Difference("", testVar, test2Var)
|
||||
if err == nil || err.Error() != "cannot convert field: true to time.Duration" {
|
||||
t.Errorf("Expected <cannot convert field: true to time.Duration> ,received: <%+v>", err)
|
||||
}
|
||||
@@ -1416,7 +1416,7 @@ func TestReflectDifferenceFloat64Error(t *testing.T) {
|
||||
var test2Var bool
|
||||
testVar = 2.5
|
||||
test2Var = true
|
||||
_, err := Difference(testVar, test2Var)
|
||||
_, err := Difference("", testVar, test2Var)
|
||||
if err == nil || err.Error() != "cannot convert field: true to float64" {
|
||||
t.Errorf("Expected <cannot convert field: true to float64> ,received: <%+v>", err)
|
||||
}
|
||||
@@ -1429,7 +1429,7 @@ func TestReflectDifferenceInt64Error(t *testing.T) {
|
||||
testVar = 6
|
||||
test2Var = 5
|
||||
expected = 1
|
||||
dif, _ := Difference(testVar, test2Var)
|
||||
dif, _ := Difference("", testVar, test2Var)
|
||||
if !reflect.DeepEqual(dif, expected) {
|
||||
t.Errorf("Expected <%+v> ,received: <%+v>", expected, dif)
|
||||
}
|
||||
@@ -1440,7 +1440,7 @@ func TestReflectDifferenceDefault(t *testing.T) {
|
||||
var test2Var bool
|
||||
testVar = true
|
||||
test2Var = true
|
||||
_, err := Difference(testVar, test2Var)
|
||||
_, err := Difference("", testVar, test2Var)
|
||||
if err == nil || err.Error() != "unsupported type" {
|
||||
t.Errorf("Expected <unsupported type> ,received: <%+v>", err)
|
||||
}
|
||||
@@ -1615,14 +1615,14 @@ func TestSumTimeTime(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDifferenceTimeTimeError(t *testing.T) {
|
||||
_, err := Difference(time.Now(), "cat")
|
||||
_, err := Difference("", time.Now(), "cat")
|
||||
if err == nil || err.Error() != "time: invalid duration \"cat\"" {
|
||||
t.Errorf("Expected <time: invalid duration \"cat\"> ,received: <%+v>", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDifferenceInt64Error(t *testing.T) {
|
||||
_, err := Difference(int64(2), "cat")
|
||||
_, err := Difference("", int64(2), "cat")
|
||||
if err == nil || err.Error() != "strconv.ParseInt: parsing \"cat\": invalid syntax" {
|
||||
t.Errorf("Expected <strconv.ParseInt: parsing \"cat\": invalid syntax> ,received: <%+v>", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user