Removed unused functions and tests in utils

This commit is contained in:
andronache
2020-11-11 15:55:58 +02:00
committed by Dan Christian Bogos
parent ae1eeb35ab
commit ae76b8af50
13 changed files with 17 additions and 908 deletions

View File

@@ -456,83 +456,6 @@ type AttrGetAccountsCount struct {
Tenant string
}
type AttrExpFileCdrs struct {
CdrFormat *string // Cdr output file format <CdreCdrFormats>
FieldSeparator *string // Separator used between fields
ExportId *string // Optional exportid
ExportDir *string // If provided it overwrites the configured export directory
ExportFileName *string // If provided the output filename will be set to this
ExportTemplate *string // Exported fields template <""|fld1,fld2|*xml:instance_name>
CgrIds []string // If provided, it will filter based on the cgrids present in list
MediationRunIds []string // If provided, it will filter on mediation runid
TORs []string // If provided, filter on TypeOfRecord
CdrHosts []string // If provided, it will filter cdrhost
CdrSources []string // If provided, it will filter cdrsource
ReqTypes []string // If provided, it will fiter reqtype
Tenants []string // If provided, it will filter tenant
Categories []string // If provided, it will filter çategory
Accounts []string // If provided, it will filter account
Subjects []string // If provided, it will filter the rating subject
DestinationPrefixes []string // If provided, it will filter on destination prefix
OrderIdStart *int64 // Export from this order identifier
OrderIdEnd *int64 // Export smaller than this order identifier
TimeStart string // If provided, it will represent the starting of the CDRs interval (>=)
TimeEnd string // If provided, it will represent the end of the CDRs interval (<)
SkipErrors bool // Do not export errored CDRs
SkipRated bool // Do not export rated CDRs
SuppressCgrIds bool // Disable CgrIds reporting in reply/ExportedCgrIds and reply/UnexportedCgrIds
Paginator
}
func (aefc *AttrExpFileCdrs) AsCDRsFilter(timezone string) (*CDRsFilter, error) {
cdrFltr := &CDRsFilter{
CGRIDs: aefc.CgrIds,
RunIDs: aefc.MediationRunIds,
ToRs: aefc.TORs,
OriginHosts: aefc.CdrHosts,
Sources: aefc.CdrSources,
RequestTypes: aefc.ReqTypes,
Tenants: aefc.Tenants,
Categories: aefc.Categories,
Accounts: aefc.Accounts,
Subjects: aefc.Subjects,
DestinationPrefixes: aefc.DestinationPrefixes,
OrderIDStart: aefc.OrderIdStart,
OrderIDEnd: aefc.OrderIdEnd,
Paginator: aefc.Paginator,
}
if len(aefc.TimeStart) != 0 {
if answerTimeStart, err := ParseTimeDetectLayout(aefc.TimeStart, timezone); err != nil {
return nil, err
} else {
cdrFltr.AnswerTimeStart = &answerTimeStart
}
}
if len(aefc.TimeEnd) != 0 {
if answerTimeEnd, err := ParseTimeDetectLayout(aefc.TimeEnd, timezone); err != nil {
return nil, err
} else {
cdrFltr.AnswerTimeEnd = &answerTimeEnd
}
}
if aefc.SkipRated {
cdrFltr.MaxCost = Float64Pointer(-1.0)
} else if aefc.SkipErrors {
cdrFltr.MinCost = Float64Pointer(0.0)
cdrFltr.MaxCost = Float64Pointer(-1.0)
}
return cdrFltr, nil
}
type ExportedFileCdrs struct {
ExportedFilePath string // Full path to the newly generated export file
TotalRecords int // Number of CDRs to be exported
TotalCost float64 // Sum of all costs in exported CDRs
FirstOrderId, LastOrderId int64 // The order id of the last exported CDR
ExportedCgrIds []string // List of successfuly exported cgrids in the file
UnexportedCgrIds map[string]string // Map of errored CDRs, map key is cgrid, value will be the error string
}
type AttrGetCdrs struct {
CgrIds []string // If provided, it will filter based on the cgrids present in list
MediationRunIds []string // If provided, it will filter on mediation runid

View File

@@ -368,85 +368,6 @@ func TestTPAccountActionsKeyId(t *testing.T) {
}
func TestAttrExpFileCdrsAsCDRsFilter(t *testing.T) {
attrExpFileCdrs := &AttrExpFileCdrs{
TimeStart: "2020-04-04T11:45:26.371Z",
TimeEnd: "2020-04-04T11:46:26.371Z",
SkipRated: true,
CgrIds: []string{"CGRID"},
TORs: []string{VOICE},
Accounts: []string{"1001"},
Subjects: []string{"1001"},
}
eOut := &CDRsFilter{
CGRIDs: attrExpFileCdrs.CgrIds,
RunIDs: attrExpFileCdrs.MediationRunIds,
ToRs: attrExpFileCdrs.TORs,
OriginHosts: attrExpFileCdrs.CdrHosts,
Sources: attrExpFileCdrs.CdrSources,
RequestTypes: attrExpFileCdrs.ReqTypes,
Tenants: attrExpFileCdrs.Tenants,
Categories: attrExpFileCdrs.Categories,
Accounts: attrExpFileCdrs.Accounts,
Subjects: attrExpFileCdrs.Subjects,
DestinationPrefixes: attrExpFileCdrs.DestinationPrefixes,
OrderIDStart: attrExpFileCdrs.OrderIdStart,
OrderIDEnd: attrExpFileCdrs.OrderIdEnd,
Paginator: attrExpFileCdrs.Paginator,
MaxCost: Float64Pointer(-1.0),
}
//check with wrong time-zone
rcv, err := attrExpFileCdrs.AsCDRsFilter("wrongtimezone")
if err == nil {
t.Errorf("ParseTimeDetectLayout error")
}
//check with wrong TimeStart
attrExpFileCdrs.TimeStart = "wrongtimeStart"
rcv, err = attrExpFileCdrs.AsCDRsFilter("")
if err == nil {
t.Errorf("Wrong AnswerTimeStart not processed")
}
//check with wrong TimeEnd
attrExpFileCdrs.TimeStart = "2020-04-04T11:45:26.371Z"
attrExpFileCdrs.TimeEnd = "wrongtimeEnd"
rcv, err = attrExpFileCdrs.AsCDRsFilter("")
if err == nil {
t.Errorf("Wrong AnswerTimeEnd not processed")
}
//check with SkipRated = true & normal timeStar/timeEnd
attrExpFileCdrs.TimeStart = "2020-04-04T11:45:26.371Z"
attrExpFileCdrs.TimeEnd = "2020-04-04T11:46:26.371Z"
TimeStart, _ := ParseTimeDetectLayout("2020-04-04T11:45:26.371Z", "")
eOut.AnswerTimeStart = &TimeStart
timeEnd, _ := ParseTimeDetectLayout("2020-04-04T11:46:26.371Z", "")
eOut.AnswerTimeEnd = &timeEnd
rcv, err = attrExpFileCdrs.AsCDRsFilter("")
if err != nil {
t.Errorf("ParseTimeDetectLayout error")
}
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expected: %s ,received: %s ", ToJSON(eOut), ToJSON(rcv))
}
//check with SkipRated = false
attrExpFileCdrs.SkipRated = false
attrExpFileCdrs.SkipErrors = true
eOut.MinCost = Float64Pointer(0.0)
rcv, err = attrExpFileCdrs.AsCDRsFilter("")
if err != nil {
t.Errorf("ParseTimeDetectLayout error")
}
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expected: %s ,received: %s ", ToJSON(eOut), ToJSON(rcv))
}
}
//now working here
func TestAttrGetCdrsAsCDRsFilter(t *testing.T) {
attrGetCdrs := &AttrGetCdrs{

View File

@@ -31,7 +31,6 @@ import (
"errors"
"fmt"
"io"
"log"
"math"
math_rand "math/rand"
"os"
@@ -134,10 +133,7 @@ func Sha1(attrs ...string) string {
// helper function for uuid generation
func GenUUID() string {
b := make([]byte, 16)
_, err := io.ReadFull(rand.Reader, b)
if err != nil {
log.Fatal(err)
}
io.ReadFull(rand.Reader, b)
b[6] = (b[6] & 0x0F) | 0x40
b[8] = (b[8] &^ 0x40) | 0x80
return fmt.Sprintf("%x-%x-%x-%x-%x", b[:4], b[4:6], b[6:8], b[8:10],
@@ -565,35 +561,6 @@ func FmtFieldWidth(fieldID, source string, width int, strip, padding string, man
return source, nil
}
// Returns the string representation of iface or error if not convertible
func CastIfToString(iface interface{}) (strVal string, casts bool) {
switch iface.(type) {
case string:
strVal = iface.(string)
casts = true
case int:
strVal = strconv.Itoa(iface.(int))
casts = true
case int64:
strVal = strconv.FormatInt(iface.(int64), 10)
casts = true
case float64:
strVal = strconv.FormatFloat(iface.(float64), 'f', -1, 64)
casts = true
case bool:
strVal = strconv.FormatBool(iface.(bool))
casts = true
case []uint8:
var byteVal []byte
if byteVal, casts = iface.([]byte); casts {
strVal = string(byteVal)
}
default: // Maybe we are lucky and the value converts to string
strVal, casts = iface.(string)
}
return strVal, casts
}
func GetEndOfMonth(ref time.Time) time.Time {
if ref.IsZero() {
return time.Now()
@@ -688,13 +655,6 @@ func (slc Int64Slice) Less(i, j int) bool {
return slc[i] < slc[j]
}
// CapitalizeErrorMessage returns the capitalized version of an error, useful in APIs
func CapitalizedMessage(errMessage string) (capStr string) {
capStr = strings.ToUpper(errMessage)
capStr = strings.Replace(capStr, " ", "_", -1)
return
}
func GetCGRVersion() (vers string, err error) {
vers = fmt.Sprintf("%s@%s", CGRateS, VERSION)
if GitLastLog == "" {

View File

@@ -852,51 +852,6 @@ func TestFmtFieldWidth(t *testing.T) {
}
}
func TestCastIfToString(t *testing.T) {
v := interface{}("somestr")
if sOut, casts := CastIfToString(v); !casts {
t.Error("Does not cast")
} else if sOut != "somestr" {
t.Errorf("Received: %+v", sOut)
}
v = interface{}(1)
if sOut, casts := CastIfToString(v); !casts {
t.Error("Does not cast")
} else if sOut != "1" {
t.Errorf("Received: %+v", sOut)
}
v = interface{}((int64)(1))
if sOut, casts := CastIfToString(v); !casts {
t.Error("Does not cast")
} else if sOut != "1" {
t.Errorf("Received: %+v", sOut)
}
v = interface{}(true)
if sOut, casts := CastIfToString(v); !casts {
t.Error("Does not cast")
} else if sOut != "true" {
t.Errorf("Received: %+v", sOut)
}
v = interface{}([]byte("test"))
if sOut, casts := CastIfToString(v); !casts {
t.Error("Does not cast")
} else if sOut != "test" {
t.Errorf("Received: %+v", sOut)
}
v = interface{}(1.2)
if sOut, casts := CastIfToString(v); !casts {
t.Error("Does not cast")
} else if sOut != "1.2" {
t.Errorf("Received: %+v", sOut)
}
//default
v = interface{}([]string{"test"})
if _, casts := CastIfToString(v); casts {
t.Error("Does cast")
}
}
func TestEndOfMonth(t *testing.T) {
eom := GetEndOfMonth(time.Date(2016, time.February, 5, 10, 1, 2, 3, time.UTC))
expected := time.Date(2016, time.February, 29, 23, 59, 59, 0, time.UTC)
@@ -1197,12 +1152,6 @@ func TestLess(t *testing.T) {
}
}
func TestCapitalizedMessage(t *testing.T) {
if capMsg := CapitalizedMessage(ServiceAlreadyRunning); capMsg != "SERVICE_ALREADY_RUNNING" {
t.Errorf("Received: <%s>", capMsg)
}
}
func TestGetCGRVersion(t *testing.T) {
GitLastLog = `commit 73014daa0c1d7edcb532d5fe600b8a20d588cdf8
Author: DanB <danb@cgrates.org>

View File

@@ -23,46 +23,6 @@ import (
"strings"
)
// Converts map[string]string into map[string]interface{}
func ConvertMapValStrIf(inMap map[string]string) map[string]interface{} {
outMap := make(map[string]interface{})
for field, val := range inMap {
outMap[field] = val
}
return outMap
}
// Mirrors key/val
func MirrorMap(mapIn map[string]string) map[string]string {
mapOut := make(map[string]string, len(mapIn))
for key, val := range mapIn {
mapOut[val] = key
}
return mapOut
}
// Returns mising keys in a map
func MissingMapKeys(inMap map[string]string, requiredKeys []string) []string {
missingKeys := []string{}
for _, reqKey := range requiredKeys {
if val, hasKey := inMap[reqKey]; !hasKey || val == EmptyString {
missingKeys = append(missingKeys, reqKey)
}
}
return missingKeys
}
// Return map keys
func MapKeys(m map[string]string) []string {
n := make([]string, len(m))
i := 0
for k := range m {
n[i] = k
i++
}
return n
}
type StringMap map[string]bool
func NewStringMap(s ...string) StringMap {
@@ -173,21 +133,6 @@ func (sm StringMap) HasKey(key string) (has bool) {
return
}
// Used to merge multiple maps (eg: output of struct having ExtraFields)
func MergeMapsStringIface(mps ...map[string]interface{}) (outMp map[string]interface{}) {
outMp = make(map[string]interface{})
for i, mp := range mps {
if i == 0 {
outMp = mp
continue
}
for k, v := range mp {
outMp[k] = v
}
}
return
}
func MapStringToInt64(in map[string]string) (out map[string]int64, err error) {
mapout := make(map[string]int64, len(in))
for key, val := range in {

View File

@@ -23,85 +23,6 @@ import (
"testing"
)
func TestConvertMapValStrIf(t *testing.T) {
var mapIn map[string]string
var mapOut map[string]interface{}
if rcv := ConvertMapValStrIf(mapIn); reflect.TypeOf(rcv) != reflect.TypeOf(mapOut) {
t.Errorf("Expecting: %+v, received: %+v", reflect.TypeOf(mapOut), reflect.TypeOf(rcv))
}
mapIn = map[string]string{"test1": "_test1_", "test2": "_test2_"}
if rcv := ConvertMapValStrIf(mapIn); reflect.TypeOf(rcv) != reflect.TypeOf(mapOut) {
t.Errorf("Expecting: %+v, received: %+v", reflect.TypeOf(mapOut), reflect.TypeOf(rcv))
} else if !reflect.DeepEqual(mapIn["test1"], rcv["test1"]) {
t.Errorf("Expecting: %+v, received: %+v", mapIn["test1"], rcv["test1"])
} else if len(rcv) != len(mapIn) {
t.Errorf("Expecting: %+v, received: %+v", len(mapIn), len(rcv))
}
}
func TestMirrorMap(t *testing.T) {
var mapIn map[string]string
if rcv := MirrorMap(mapIn); reflect.DeepEqual(rcv, mapIn) {
t.Errorf("Expecting: %+v, received: %+v", reflect.TypeOf(mapIn), reflect.TypeOf(rcv))
} else if len(rcv) != 0 {
t.Errorf("Expecting: %+v, received: %+v", 0, len(rcv))
}
mapIn = map[string]string{"test1": "_test1_", "test2": "_test2_"}
eOut := map[string]string{"_test1_": "test1", "_test2_": "test2"}
if rcv := MirrorMap(mapIn); reflect.DeepEqual(rcv, mapIn) {
t.Errorf("Expecting: %+v, received: %+v", reflect.TypeOf(mapIn), reflect.TypeOf(rcv))
} else if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestMissingMapKeys(t *testing.T) {
mapIn := map[string]string{}
requiredKeys := []string{}
if rcv := MissingMapKeys(mapIn, requiredKeys); len(rcv) != 0 {
t.Errorf("Expecting: %+v, received: %+v", 0, len(rcv))
}
mapIn = map[string]string{"test1": "_test1_", "test2": "_test2_"}
requiredKeys = []string{"test1", "test2"}
if rcv := MissingMapKeys(mapIn, requiredKeys); len(rcv) != 0 {
t.Errorf("Expecting: %+v, received: %+v", 0, len(rcv))
}
mapIn = map[string]string{"test1": "_test1_", "test2": "_test2_"}
requiredKeys = []string{"test2", "test3"}
if rcv := MissingMapKeys(mapIn, requiredKeys); len(rcv) != 1 {
t.Errorf("Expecting: %+v, received: %+v", 1, len(rcv))
} else if !reflect.DeepEqual([]string{"test3"}, rcv) {
t.Errorf("Expecting: %+v, received: %+v", []string{"test3"}, rcv)
}
requiredKeys = []string{"test3", "test4"}
eOut := []string{"test3", "test4"}
if rcv := MissingMapKeys(mapIn, requiredKeys); len(rcv) != 2 {
t.Errorf("Expecting: %+v, received: %+v", 2, len(rcv))
} else if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestMapKeys(t *testing.T) {
mapIn := map[string]string{"test1": "_test1_", "test2": "_test2_"}
eOut := []string{"test1", "test2"}
rcv := MapKeys(mapIn)
sort.Slice(rcv, func(i, j int) bool { return rcv[i] < rcv[j] })
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
mapIn = map[string]string{"test1": "_test1_", "test2": "_test2_", "test3": "_test3_", "test4": "_test4_"}
eOut = []string{"test1", "test2", "test3", "test4"}
rcv = MapKeys(mapIn)
sort.Slice(rcv, func(i, j int) bool { return rcv[i] < rcv[j] })
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestMapKeysStringMapParse(t *testing.T) {
if sm := ParseStringMap(EmptyString); len(sm) != 0 {
t.Errorf("Expecting %+v, received %+v", 0, len(sm))
@@ -133,27 +54,6 @@ func TestMapKeysStringMapParse(t *testing.T) {
}
}
func TestMapMergeMapsStringIface(t *testing.T) {
mp1 := map[string]interface{}{
"Hdr1": "Val1",
"Hdr2": "Val2",
"Hdr3": "Val3",
}
mp2 := map[string]interface{}{
"Hdr3": "Val4",
"Hdr4": "Val4",
}
eMergedMap := map[string]interface{}{
"Hdr1": "Val1",
"Hdr2": "Val2",
"Hdr3": "Val4",
"Hdr4": "Val4",
}
if mergedMap := MergeMapsStringIface(mp1, mp2); !reflect.DeepEqual(eMergedMap, mergedMap) {
t.Errorf("Expecting: %+v, received: %+v", eMergedMap, mergedMap)
}
}
func TestEqual(t *testing.T) {
t1 := NewStringMap("val1")
t2 := NewStringMap("val2")

View File

@@ -94,3 +94,19 @@ func TestDecodeServerRequest(t *testing.T) {
t.Errorf("Expecting: %+v, received: %+v", err, rcvErr)
}
}
func TestWriteServerResponse(t *testing.T) {
writer := bytes.NewBufferString(EmptyString)
var id *json.RawMessage
var result interface{} = "OK"
var errMessage interface{}
slsByte := []byte("10")
id = (*json.RawMessage)(&slsByte)
if err := WriteServerResponse(writer, id, result, errMessage); err != nil {
t.Errorf("Expecting: <nil>, received: <%+v>", err)
}
if writer.String() != "{\"id\":10,\"result\":\"OK\",\"error\":null}\n" {
t.Errorf("Expecting: <{\"id\":10,\"result\":\"OK\",\"error\":null}>, received: <%+v>", writer.String())
}
}

View File

@@ -360,23 +360,6 @@ func IfaceAsSliceString(fld interface{}) (out []string, err error) {
return
}
// AsMapStringIface converts an item (mostly struct) as map[string]interface{}
func AsMapStringIface(item interface{}) (map[string]interface{}, error) {
out := make(map[string]interface{})
v := reflect.ValueOf(item)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct { // Only structs for now
return nil, fmt.Errorf("AsMapStringIface only accepts structs; got %T", v)
}
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
out[typ.Field(i).Name] = v.Field(i).Interface()
}
return out, nil
}
func GetUniformType(item interface{}) (interface{}, error) {
valItm := reflect.ValueOf(item)
switch valItm.Kind() { // convert evreting to float64

View File

@@ -121,28 +121,6 @@ func TestReflectFieldAsStringOnMap(t *testing.T) {
}
}
func TestReflectAsMapStringIface(t *testing.T) {
mystruct := struct {
Title string
Count int
Count64 int64
Val float64
ExtraFields map[string]interface{}
}{"Title1", 5, 6, 7.3, map[string]interface{}{"a": "Title2", "b": 15, "c": int64(16), "d": 17.3}}
expectOutMp := map[string]interface{}{
"Title": "Title1",
"Count": 5,
"Count64": int64(6),
"Val": 7.3,
"ExtraFields": map[string]interface{}{"a": "Title2", "b": 15, "c": int64(16), "d": 17.3},
}
if outMp, err := AsMapStringIface(mystruct); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expectOutMp, outMp) {
t.Errorf("Expecting: %+v, received: %+v", expectOutMp, outMp)
}
}
func TestGreaterThan(t *testing.T) {
if gte, err := GreaterThan(1, 1.2, false); err != nil {
t.Error(err)

View File

@@ -36,46 +36,6 @@ func SliceHasMember(ss []string, s string) bool {
return i < len(ss) && ss[i] == s
}
// SliceWithoutMember removes s string from slice ss (if found)
func SliceWithoutMember(ss []string, s string) []string {
sort.Strings(ss)
if i := sort.SearchStrings(ss, s); i < len(ss) && ss[i] == s {
ss[i], ss = ss[len(ss)-1], ss[:len(ss)-1]
}
return ss
}
// Iterates over slice members and returns true if one starts with prefix
func SliceMemberHasPrefix(ss []string, prfx string) bool {
for _, mbr := range ss {
if strings.HasPrefix(mbr, prfx) {
return true
}
}
return false
}
// Avg returns the average of a float64 slice
func Avg(values []float64) float64 {
if len(values) == 0 {
return 0.0
}
var sum float64
for _, val := range values {
sum += val
}
return sum / float64(len(values))
}
// AvgNegative returns the average of a float64 slice
// if is called with an empty slice return -1
func AvgNegative(values []float64) float64 {
if len(values) == 0 {
return -1 // return -1 if no data
}
return Avg(values)
}
// PrefixSliceItems iterates through slice and add a prefix before every element
func PrefixSliceItems(slc []string, prfx string) (out []string) {
out = make([]string, len(slc))
@@ -85,14 +45,6 @@ func PrefixSliceItems(slc []string, prfx string) (out []string) {
return
}
// StripSlicePrefix will strip a number of items from the beginning of the slice
func StripSlicePrefix(slc []string, nrItems int) []string {
if len(slc) < nrItems {
return []string{}
}
return slc[nrItems:]
}
// SliceStringToIface converts slice of strings into a slice of interfaces
func SliceStringToIface(slc []string) (ifc []interface{}) {
ifc = make([]interface{}, len(slc))

View File

@@ -49,29 +49,6 @@ func TestFlaot64SliceHasMember(t *testing.T) {
t.Error("Expecting: true, received: false")
}
}
func TestSliceWithoutMember(t *testing.T) {
rcv := SliceWithoutMember([]string{"1", "2", "3", "4", "5"}, "5")
sort.Strings(rcv)
eOut := []string{"1", "2", "3", "4"}
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
rcv = SliceWithoutMember([]string{"1", "2", "3", "4", "5"}, "6")
sort.Strings(rcv)
eOut = []string{"1", "2", "3", "4", "5"}
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestSliceMemberHasPrefix(t *testing.T) {
if !SliceMemberHasPrefix([]string{"1", "*2", "3", "4", "5"}, "*") {
t.Error("Expecting: true, received: false")
}
if SliceMemberHasPrefix([]string{"1", "2", "3", "4", "5"}, "*") {
t.Error("Expecting: true, received: false")
}
}
func TestHasPrefixSlice(t *testing.T) {
if !HasPrefixSlice([]string{"1", "2", "3", "4", "5"}, "123") {
@@ -82,30 +59,6 @@ func TestHasPrefixSlice(t *testing.T) {
}
}
func TestAvg(t *testing.T) {
if rcv := Avg([]float64{}); rcv != 0 {
t.Errorf("Expecting: 0, received: %+v", rcv)
}
if rcv := Avg([]float64{1, 2, 3}); rcv != 2 {
t.Errorf("Expecting: 2, received: %+v", rcv)
}
if rcv := Avg([]float64{1.5, 2.75, 3.25}); rcv != 2.5 {
t.Errorf("Expecting: 2.5, received: %+v", rcv)
}
}
func TestAvgNegative(t *testing.T) {
if rcv := AvgNegative([]float64{}); rcv != -1 {
t.Errorf("Expecting: -1, received: %+v", rcv)
}
if rcv := AvgNegative([]float64{1, 2, 3}); rcv != 2 {
t.Errorf("Expecting: 2, received: %+v", rcv)
}
if rcv := Avg([]float64{1.5, 2.75, 3.25}); rcv != 2.5 {
t.Errorf("Expecting: 2.5, received: %+v", rcv)
}
}
func TestPrefixSliceItems(t *testing.T) {
rcv := PrefixSliceItems([]string{"1", "2", "3", "4", "5"}, "*")
sort.Strings(rcv)
@@ -115,21 +68,6 @@ func TestPrefixSliceItems(t *testing.T) {
}
}
func TestStripSlicePrefix(t *testing.T) {
eSlc := make([]string, 0)
if retSlc := StripSlicePrefix([]string{}, 2); !reflect.DeepEqual(eSlc, retSlc) {
t.Errorf("expecting: %+v, received: %+v", eSlc, retSlc)
}
eSlc = []string{"1", "2"}
if retSlc := StripSlicePrefix([]string{"0", "1", "2"}, 1); !reflect.DeepEqual(eSlc, retSlc) {
t.Errorf("expecting: %+v, received: %+v", eSlc, retSlc)
}
eSlc = []string{}
if retSlc := StripSlicePrefix([]string{"0", "1", "2"}, 3); !reflect.DeepEqual(eSlc, retSlc) {
t.Errorf("expecting: %+v, received: %+v", eSlc, retSlc)
}
}
func TestSliceStringToIface(t *testing.T) {
exp := []interface{}{"*default", "ToR", "*voice"}
if rply := SliceStringToIface([]string{"*default", "ToR", "*voice"}); !reflect.DeepEqual(exp, rply) {

View File

@@ -19,10 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package utils
import (
"errors"
"fmt"
"reflect"
"strconv"
"strings"
)
@@ -44,30 +42,6 @@ func MissingStructFields(s interface{}, mandatories []string) []string {
return missing
}
// Detects nonempty struct fields, s should be a pointer to a struct
// Useful to not overwrite db fields with non defined params in api
func NonemptyStructFields(s interface{}) map[string]interface{} {
fields := make(map[string]interface{})
for i := 0; i < reflect.ValueOf(s).Elem().NumField(); i++ {
fld := reflect.ValueOf(s).Elem().Field(i)
switch fld.Kind() {
case reflect.Bool:
fields[reflect.TypeOf(s).Elem().Field(i).Name] = fld.Bool()
case reflect.Int:
fieldVal := fld.Int()
if fieldVal != 0 {
fields[reflect.TypeOf(s).Elem().Field(i).Name] = fieldVal
}
case reflect.String:
fieldVal := fld.String()
if fieldVal != "" {
fields[reflect.TypeOf(s).Elem().Field(i).Name] = fieldVal
}
}
}
return fields
}
// MissingMapFields detects missing field values based on mandatory field names from a map[string]interface{}
func MissingMapFields(s map[string]interface{}, mandatories []string) []string {
missing := []string{}
@@ -90,158 +64,6 @@ func MissingMapFields(s map[string]interface{}, mandatories []string) []string {
return missing
}
// Converts a struct to map[string]string
func ToMapStringString(in interface{}) map[string]string {
out := make(map[string]string)
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
in = v.Interface()
}
typ := reflect.TypeOf(in)
for i := 0; i < v.NumField(); i++ {
// gets us a StructField
typField := typ.Field(i)
field := v.Field(i)
if field.Kind() == reflect.String {
out[typField.Name] = field.String()
}
}
return out
}
func GetMapExtraFields(in interface{}, extraFields string) map[string]string {
out := make(map[string]string)
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
field := v.FieldByName(extraFields)
if field.Kind() == reflect.Map {
keys := field.MapKeys()
for _, key := range keys {
out[key.String()] = field.MapIndex(key).String()
}
}
return out
}
func SetMapExtraFields(in interface{}, values map[string]string, extraFields string) {
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
efField := v.FieldByName(extraFields)
if efField.IsValid() && efField.Kind() == reflect.Map {
keys := efField.MapKeys()
for _, key := range keys {
if efField.MapIndex(key).String() != "" {
if val, found := values[key.String()]; found {
efField.SetMapIndex(key, reflect.ValueOf(val))
}
}
}
}
return
}
func FromMapStringString(m map[string]string, in interface{}) {
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
for fieldName, fieldValue := range m {
field := v.FieldByName(fieldName)
if field.IsValid() {
if field.Kind() == reflect.String {
if field.String() != "" && field.CanSet() {
field.SetString(fieldValue)
}
}
}
}
return
}
func FromMapStringInterface(m map[string]interface{}, in interface{}) error {
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
for fieldName, fieldValue := range m {
field := v.FieldByName(fieldName)
if field.IsValid() {
if !field.IsValid() || !field.CanSet() {
continue
}
structFieldType := field.Type()
val := reflect.ValueOf(fieldValue)
if structFieldType != val.Type() {
return errors.New("Provided value type didn't match obj field type")
}
field.Set(val)
}
}
return nil
}
// initial intent was to use it with *cgr_rpc but does not handle slice and structure fields
func FromMapStringInterfaceValue(m map[string]interface{}, v reflect.Value) (interface{}, error) {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
for fieldName, fieldValue := range m {
field := v.FieldByName(fieldName)
if field.IsValid() {
if !field.IsValid() || !field.CanSet() {
continue
}
val := reflect.ValueOf(fieldValue)
structFieldType := field.Type()
if structFieldType.Kind() == reflect.Ptr {
field.Set(reflect.New(field.Type().Elem()))
field = field.Elem()
}
structFieldType = field.Type()
if structFieldType != val.Type() {
return nil, fmt.Errorf("provided value type didn't match obj field type: %v vs %v (%v vs %v)", structFieldType, val.Type(), structFieldType.Kind(), val.Type().Kind())
}
field.Set(val)
}
}
return v.Interface(), nil
}
// Update struct with map fields, returns not matching map keys, s is a struct to be updated
func UpdateStructWithStrMap(s interface{}, m map[string]string) []string { // Not tested and declared and used only here
notMatched := []string{}
for key, val := range m {
fld := reflect.ValueOf(s).Elem().FieldByName(key)
if fld.IsValid() {
switch fld.Kind() {
case reflect.Bool:
if valBool, err := strconv.ParseBool(val); err != nil {
notMatched = append(notMatched, key)
} else {
fld.SetBool(valBool)
}
case reflect.Int:
if valInt, err := strconv.ParseInt(val, 10, 64); err != nil {
notMatched = append(notMatched, key)
} else {
fld.SetInt(valInt)
}
case reflect.String:
fld.SetString(val)
}
} else {
notMatched = append(notMatched, key)
}
}
return notMatched
}
// UpdateStructWithIfaceMap will update struct fields with values coming from map
// if map values are not matching the ones in struct convertion is being attempted
// ToDo: add here more fields

View File

@@ -36,164 +36,6 @@ func TestMissingStructFieldsCorrect(t *testing.T) {
}
}
func TestStructMapStruct(t *testing.T) {
type TestStruct struct {
Name string
Surname string
Address string
Other string
}
ts := &TestStruct{
Name: "1",
Surname: "2",
Address: "3",
Other: "",
}
nts := &TestStruct{
Name: "1",
Surname: "2",
Address: "3",
Other: "",
}
m := ToMapStringString(ts)
FromMapStringString(m, ts)
if !reflect.DeepEqual(ts, nts) {
t.Log(m)
t.Errorf("Expected: %+v got: %+v", ts, nts)
}
}
func TestMapStructAddStructs(t *testing.T) {
type TestStruct struct {
Name string
Surname string
Address string
Other string
}
ts := &TestStruct{
Name: "1",
Surname: "2",
Address: "3",
Other: "",
}
nts := &TestStruct{
Name: "1",
Surname: "2",
Address: "3",
Other: "",
}
m := ToMapStringString(ts)
m["Test"] = "4"
FromMapStringString(m, ts)
if !reflect.DeepEqual(ts, nts) {
t.Log(m)
t.Errorf("Expected: %+v got: %+v", ts, nts)
}
}
func TestStructExtraFields(t *testing.T) {
ts := struct {
Name string
Surname string
Address string
ExtraFields map[string]string
}{
Name: "1",
Surname: "2",
Address: "3",
ExtraFields: map[string]string{
"k1": "v1",
"k2": "v2",
"k3": "v3",
},
}
efMap := GetMapExtraFields(ts, "ExtraFields")
if !reflect.DeepEqual(efMap, ts.ExtraFields) {
t.Errorf("expected: %v got: %v", ts.ExtraFields, efMap)
}
}
func TestSetStructExtraFields(t *testing.T) {
ts := struct {
Name string
Surname string
Address string
ExtraFields map[string]string
}{
Name: "1",
Surname: "2",
Address: "3",
ExtraFields: make(map[string]string),
}
s := "ExtraFields"
m := map[string]string{
"k1": "v1",
"k2": "v2",
"k3": "v3",
}
SetMapExtraFields(ts, m, s)
efMap := GetMapExtraFields(ts, "ExtraFields")
if !reflect.DeepEqual(efMap, ts.ExtraFields) {
t.Errorf("expected: %v got: %v", ts.ExtraFields, efMap)
}
}
func TestStructFromMapStringInterface(t *testing.T) {
ts := &struct {
Name string
Class *string
List []string
Elements struct {
Type string
Value float64
}
}{}
s := "test2"
m := map[string]interface{}{
"Name": "test1",
"Class": &s,
"List": []string{"test3", "test4"},
"Elements": struct {
Type string
Value float64
}{
Type: "test5",
Value: 9.8,
},
}
if err := FromMapStringInterface(m, ts); err != nil {
t.Logf("ts: %+v", ToJSON(ts))
t.Error("Error converting map to struct: ", err)
}
}
func TestStructFromMapStringInterfaceValue(t *testing.T) {
type T struct {
Name string
Disabled *bool
Members []string
}
ts := &T{}
vts := reflect.ValueOf(ts)
x, err := FromMapStringInterfaceValue(map[string]interface{}{
"Name": "test",
"Disabled": true,
"Members": []string{"1", "2", "3"},
}, vts)
rt := x.(T)
if err != nil {
t.Fatalf("error converting structure value: %v", err)
}
if rt.Name != "test" ||
*rt.Disabled != true ||
!reflect.DeepEqual(rt.Members, []string{"1", "2", "3"}) {
t.Errorf("error converting structure value: %s", ToIJSON(rt))
}
}
func TestUpdateStructWithIfaceMap(t *testing.T) {
type myStruct struct {
String string
@@ -236,26 +78,6 @@ func TestUpdateStructWithIfaceMap(t *testing.T) {
}
}
func TestNonemptyStructFields(t *testing.T) {
var attr = struct {
Tenant string
Direction bool
Account string
Type string
ActionTimingsId string
}{"bevoip.eu", true, "testaccount", META_PREPAID, ""}
mapStruct := NonemptyStructFields(&attr)
expMapStruct := map[string]interface{}{
"Tenant": "bevoip.eu",
"Direction": true,
"Account": "testaccount",
"Type": META_PREPAID,
}
if !reflect.DeepEqual(expMapStruct, mapStruct) {
t.Errorf("expecting: %+v, received: %+v", expMapStruct, mapStruct)
}
}
func TestMissingMapFields(t *testing.T) {
var attr = map[string]interface{}{
Tenant: "cgrates.org",