Files
cgrates/utils/coreutils_test.go
ionutboangiu 6c41ebe0de Add sanity check to prevent xml reader panic
HierarchyPath parser now returns nil when
the path is empty (instead of a string slice with one
EmptyString element).

If the prefix is set to true, when calling the AsString
method on a nil HierarchyPath, only the separator will
be returned. This avoids a nil expr error coming from
the xmlquery library.

Use the Query and QueryAll functions from the xmlquery
package to be able to handle the errors ourselves and
avoid panics.

Remove config default value for xml_root_path. The field
will remain commented in config_defaults for reference.

Add tests for HierarchyPath.AsString function.

Add comments for XmlProvider and xml_root_path opt.
2023-10-16 13:18:12 +03:00

1911 lines
58 KiB
Go

/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package utils
import (
"errors"
"fmt"
"math"
"reflect"
"sync"
"testing"
"time"
"golang.org/x/crypto/bcrypt"
"github.com/cgrates/birpc"
"github.com/cgrates/rpcclient"
)
func TestGetStartTime(t *testing.T) {
startCGRateSTime = time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)
eOut := startCGRateSTime.Format(time.UnixDate)
rcv := GetStartTime()
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestFirstNonEmpty(t *testing.T) {
//only check with an empty string
rcv := FirstNonEmpty(EmptyString)
if rcv != EmptyString {
t.Errorf("Expecting an empty string, received: %+v", rcv)
}
//normal check
firstElmnt := ""
sampleMap := make(map[string]string)
sampleMap["Third"] = "third"
fourthElmnt := "fourth"
winnerElmnt := FirstNonEmpty(firstElmnt, sampleMap["second"], sampleMap["Third"], fourthElmnt)
if winnerElmnt != sampleMap["Third"] {
t.Error("Wrong elemnt returned: ", winnerElmnt)
}
}
func TestFirstIntNonEmpty(t *testing.T) {
//check for default value
rcv := FirstIntNonEmpty(0)
if rcv != 0 {
t.Errorf("Expected 0 \n but received \n %d", rcv)
}
//case the first non empty value is on the first position
rcv = FirstIntNonEmpty(21, 0, 0)
if rcv != 21 {
t.Errorf("Expected 21 \n but received \n %d", rcv)
}
//case the first non empty value is on the second position
rcv = FirstIntNonEmpty(0, 21, 0)
if rcv != 21 {
t.Errorf("Expected 21 \n but received \n %d", rcv)
}
//case the first non empty value is on the third position
rcv = FirstIntNonEmpty(0, 0, 21)
if rcv != 21 {
t.Errorf("Expected 21 \n but received \n %d", rcv)
}
}
func TestFirstDurationNonEmpty(t *testing.T) {
//check for default value
rcv := FirstDurationNonEmpty(0)
if rcv != 0 {
t.Errorf("Expected 0 \n but received \n %d", rcv)
}
//case the first non empty value is on the first position
rcv = FirstDurationNonEmpty(2*time.Minute, 0, 0)
if rcv != 2*time.Minute {
t.Errorf("Expected 2m \n but received \n %d", rcv)
}
//case the first non empty value is on the second position
rcv = FirstDurationNonEmpty(0, 2*time.Minute, 0)
if rcv != 2*time.Minute {
t.Errorf("Expected 2m \n but received \n %d", rcv)
}
//case the first non empty value is on the third position
rcv = FirstDurationNonEmpty(0, 0, 2*time.Minute)
if rcv != 2*time.Minute {
t.Errorf("Expected 2m \n but received \n %d", rcv)
}
}
func TestSha1(t *testing.T) {
//empty check
rcv := Sha1(" ")
eOut := "b858cb282617fb0956d960215c8e84d1ccf909c6"
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %s, received: %s", eOut, rcv)
}
//normal check
rcv = Sha1("teststring")
eOut = "b8473b86d4c2072ca9b08bd28e373e8253e865c4"
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %s, received: %s", eOut, rcv)
}
rcv = Sha1("test1", "test2")
eOut = "dff964f6e3c1761b6288f5c75c319d36fb09b2b9"
if !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %s, received: %s", eOut, rcv)
}
}
func TestSha1ReverseOrder(t *testing.T) {
rcv := Sha1("test1", "test2")
revOrd := Sha1("test2", "test1")
// Sha1 consider order when generating
if reflect.DeepEqual(revOrd, rcv) {
t.Errorf("Expecting: %s, received: %s", revOrd, rcv)
}
rcv = Sha1("test1")
revOrd = Sha1("test1")
if !reflect.DeepEqual(revOrd, rcv) {
t.Errorf("Expecting: %s, received: %s", revOrd, rcv)
}
}
func TestUUID(t *testing.T) {
uuid := GenUUID()
if len(uuid) == 0 {
t.Fatalf("GenUUID error %s", uuid)
}
uuid2 := GenUUID()
if len(uuid2) == 0 {
t.Fatalf("GenUUID error %s", uuid)
}
if uuid == uuid2 {
t.Error("GenUUID error.")
}
}
func TestUUIDSha1Prefix(t *testing.T) {
rcv := UUIDSha1Prefix()
if len(rcv) != 7 {
t.Errorf("Expected len: 7, received %d", len(rcv))
}
rcv2 := UUIDSha1Prefix()
if len(rcv2) != 7 {
t.Errorf("Expected len: 7, received %d", len(rcv))
}
if rcv == rcv2 {
t.Error("UUIDSha1Prefix error")
}
}
func TestRound(t *testing.T) {
result := Round(12.49, 1, MetaRoundingUp)
expected := 12.5
if result != expected {
t.Errorf("Error rounding up: sould be %v was %v", expected, result)
}
result = Round(12.21, 1, MetaRoundingUp)
expected = 12.3
if result != expected {
t.Errorf("Error rounding up: sould be %v was %v", expected, result)
}
result = Round(0.0701, 2, MetaRoundingUp)
expected = 0.08
if result != expected {
t.Errorf("Error rounding up: sould be %v was %v", expected, result)
}
result = Round(12.49, 1, MetaRoundingDown)
expected = 12.4
if result != expected {
t.Errorf("Error rounding down: sould be %v was %v", expected, result)
}
result = Round(12.21, 1, MetaRoundingDown)
expected = 12.2
if result != expected {
t.Errorf("Error rounding up: sould be %v was %v", expected, result)
}
//AlredyHavingPrecision
x := 0.07
if y := Round(x, 2, MetaRoundingUp); y != x {
t.Error("Error rounding when already has desired precision: ", y)
}
if y := Round(x, 2, MetaRoundingMiddle); y != x {
t.Error("Error rounding when already has desired precision: ", y)
}
if y := Round(x, 2, MetaRoundingDown); y != x {
t.Error("Error rounding when already has desired precision: ", y)
}
result = Round(14.37, 8, MetaRoundingDown)
expected = 14.37
if result != expected {
t.Errorf("Expecting: %v, received: %v", expected, result)
}
result = Round(14.37, 8, "ROUNDING_NOWHERE")
expected = 14.37
if result != expected {
t.Errorf("Expecting: %v, received: %v", expected, result)
}
result = Round(14.37, 0, MetaRoundingMiddle)
expected = 14
if result != expected {
t.Errorf("Expecting: %v, received: %v", expected, result)
}
result = Round(14.37, -1, MetaRoundingMiddle)
expected = 10
if result != expected {
t.Errorf("Expecting: %v, received: %v", expected, result)
}
}
func TestParseTimeDetectLayout(t *testing.T) {
tmStr := "2013-12-30T15:00:01Z"
expectedTime := time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC)
tm, err := ParseTimeDetectLayout(tmStr, "")
if err != nil {
t.Error(err)
} else if !tm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", tm, expectedTime)
}
_, err = ParseTimeDetectLayout(tmStr[1:], "")
if err == nil {
t.Errorf("Expecting error")
}
tmStr = "2016-04-01T02:00:00+02:00"
expectedTime = time.Date(2016, 4, 1, 0, 0, 0, 0, time.UTC)
tm, err = ParseTimeDetectLayout(tmStr, "")
if err != nil {
t.Error(err)
} else if !tm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", tm, expectedTime)
}
_, err = ParseTimeDetectLayout(tmStr[1:], "")
if err == nil {
t.Errorf("Expecting error")
}
sqlTmStr := "2013-12-30 15:00:01"
expectedTime = time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC)
sqlTm, err := ParseTimeDetectLayout(sqlTmStr, "")
if err != nil {
t.Error(err)
} else if !sqlTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", sqlTm, expectedTime)
}
_, err = ParseTimeDetectLayout(sqlTmStr[1:], "")
if err == nil {
t.Errorf("Expecting error")
}
unixTmStr := "1388415601"
unixTm, err := ParseTimeDetectLayout(unixTmStr, "")
if err != nil {
t.Error(err)
} else if !unixTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", unixTm, expectedTime)
}
_, err = ParseTimeDetectLayout(unixTmStr[1:], "")
if err == nil {
t.Errorf("Expecting error")
}
goTmStr := "2013-12-30 15:00:01 +0000 UTC"
goTm, err := ParseTimeDetectLayout(goTmStr, "")
if err != nil {
t.Error(err)
} else if !goTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", goTm, expectedTime)
}
_, err = ParseTimeDetectLayout(goTmStr[1:], "")
if err == nil {
t.Errorf("Expecting error")
}
goTmStr = "2013-12-30 15:00:01.000000000 +0000 UTC"
goTm, err = ParseTimeDetectLayout(goTmStr, "")
if err != nil {
t.Error(err)
} else if !goTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", goTm, expectedTime)
}
_, err = ParseTimeDetectLayout(goTmStr[1:], "")
if err == nil {
t.Errorf("Expecting error")
}
loc, err := time.LoadLocation("Asia/Kabul")
if err != nil {
t.Error(err)
}
expectedTime = time.Date(2013, 12, 30, 15, 0, 1, 0, loc)
goTmStr2 := "2013-12-30 15:00:01 +0430 +0430"
goTm, err = ParseTimeDetectLayout(goTmStr2, "")
if err != nil {
t.Error(err)
} else if !goTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", goTm, expectedTime)
}
//goTmStr2 = "2013-12-30 15:00:01 +0430"
//if _, err = ParseTimeDetectLayout(goTmStr2, ""); err != nil {
// t.Errorf("Expecting error")
//}
fsTmstampStr := "1394291049287234"
fsTm, err := ParseTimeDetectLayout(fsTmstampStr, "")
expectedTime = time.Date(2014, 3, 8, 15, 4, 9, 287234000, time.UTC)
if err != nil {
t.Error(err)
} else if !fsTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", fsTm, expectedTime)
}
fsTmstampStr = "9999999999999999"
fsTm, err = ParseTimeDetectLayout(fsTmstampStr, "")
if err == nil {
t.Error("Error expected: 'value out of range', received nil")
}
fsTmstampStr = "1394291049287234286"
fsTm, err = ParseTimeDetectLayout(fsTmstampStr, "")
expectedTime = time.Date(2014, 3, 8, 15, 4, 9, 287234286, time.UTC)
if err != nil {
t.Error(err)
} else if !fsTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", fsTm, expectedTime)
}
fsTmstampStr = "9999999999999999999"
fsTm, err = ParseTimeDetectLayout(fsTmstampStr, "")
if err == nil {
t.Error("Error expected: 'value out of range', received nil")
}
var nilTime time.Time
fsTmstampStr = "+9999999999999999999"
fsTm, err = ParseTimeDetectLayout(fsTmstampStr, "")
if err == nil {
t.Error("Error expected: 'value out of range', received nil")
} else if fsTm != nilTime {
t.Errorf("Expecting nilTime, received: %+v", fsTm)
}
fsTmstampStr = "0"
fsTm, err = ParseTimeDetectLayout(fsTmstampStr, "")
expectedTime = time.Time{}
if err != nil {
t.Error(err)
} else if !fsTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", fsTm, expectedTime)
}
onelineTmstampStr := "20131023215149"
olTm, err := ParseTimeDetectLayout(onelineTmstampStr, "")
expectedTime = time.Date(2013, 10, 23, 21, 51, 49, 0, time.UTC)
if err != nil {
t.Error(err)
} else if !olTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", olTm, expectedTime)
}
oneSpaceTmStr := "08.04.2014 22:14:29"
tsTm, err := ParseTimeDetectLayout(oneSpaceTmStr, "")
expectedTime = time.Date(2014, 4, 8, 22, 14, 29, 0, time.UTC)
if err != nil {
t.Error(err)
} else if !tsTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", tsTm, expectedTime)
}
if nowTm, err := ParseTimeDetectLayout(MetaNow, ""); err != nil {
t.Error(err)
} else if time.Since(nowTm) > 10*time.Millisecond {
t.Errorf("Unexpected time parsed: %v", nowTm)
}
eamonTmStr := "31/05/2015 14:46:00"
eamonTmS, err := ParseTimeDetectLayout(eamonTmStr, "")
expectedTime = time.Date(2015, 5, 31, 14, 46, 0, 0, time.UTC)
if err != nil {
t.Error(err)
} else if !eamonTmS.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", eamonTmS, expectedTime)
}
broadSoftTmStr := "20160419210007.037"
broadTmS, err := ParseTimeDetectLayout(broadSoftTmStr, "")
expectedTime = time.Date(2016, 4, 19, 21, 0, 7, 37000000, time.UTC)
if err != nil {
t.Error(err)
} else if !broadTmS.Equal(expectedTime) {
t.Errorf("Expecting: %v, received: %v", expectedTime, broadTmS)
}
astTimestamp := "2016-09-14T19:37:43.665+0000"
expectedTime = time.Date(2016, 9, 14, 19, 37, 43, 665000000, time.UTC)
astTMS, err := ParseTimeDetectLayout(astTimestamp, "")
if err != nil {
t.Error(err)
} else if !astTMS.Equal(expectedTime) {
t.Errorf("Expecting: %v, received: %v", expectedTime, astTMS)
}
nowTimeStr := "+24h"
start := time.Now().Add(23*time.Hour + 59*time.Minute + 58*time.Second)
end := start.Add(2 * time.Second)
parseNowTimeStr, err := ParseTimeDetectLayout(nowTimeStr, "")
if err != nil {
t.Error(err)
} else if parseNowTimeStr.After(start) && parseNowTimeStr.Before(end) {
t.Errorf("Unexpected time parsed: %v", parseNowTimeStr)
}
unixTmMilisecStr := "1534176053410"
expectedTime = time.Date(2018, 8, 13, 16, 00, 53, 410000000, time.UTC)
unixTm, err = ParseTimeDetectLayout(unixTmMilisecStr, "")
if err != nil {
t.Error(err)
} else if !unixTm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", unixTm, expectedTime)
}
tmStr = "2005-08-26T14:17:34"
expectedTime = time.Date(2005, 8, 26, 14, 17, 34, 0, time.UTC)
tm, err = ParseTimeDetectLayout(tmStr, "")
if err != nil {
t.Error(err)
} else if !tm.Equal(expectedTime) {
t.Errorf("Unexpected time parsed: %v, expecting: %v", tm, expectedTime)
}
expected := time.Date(2013, 7, 30, 19, 33, 10, 0, time.UTC)
date, err := ParseTimeDetectLayout("1375212790", "")
if err != nil || !date.Equal(expected) {
t.Error("error parsing date: ", expected.Sub(date))
}
date, err = ParseTimeDetectLayout("*unlimited", "")
if err != nil || !date.IsZero() {
t.Error("error parsing unlimited date!: ")
}
date, err = ParseTimeDetectLayout("", "")
if err != nil || !date.IsZero() {
t.Error("error parsing unlimited date!: ")
}
date, err = ParseTimeDetectLayout("+20s", "")
expected = time.Now()
if err != nil || date.Sub(expected).Seconds() > 20 || date.Sub(expected).Seconds() < 19 {
t.Error("error parsing date: ", date.Sub(expected).Seconds())
}
expected = time.Now().AddDate(0, 0, 1)
if date, err := ParseTimeDetectLayout("*daily", ""); err != nil {
t.Error(err)
} else if expected.Sub(date).Seconds() > 1 {
t.Errorf("received: %+v", date)
}
expected = time.Now().AddDate(0, 1, 0)
if date, err := ParseTimeDetectLayout("*monthly", ""); err != nil {
t.Error(err)
} else if expected.Sub(date).Seconds() > 1 {
t.Errorf("received: %+v", date)
}
expected = time.Now().AddDate(0, 1, 0)
if date, err := ParseTimeDetectLayout("*monthly_estimated", ""); err != nil {
t.Error(err)
} else {
initialMnt := time.Now().Month()
for expected.Month()-initialMnt > 1 {
expected = expected.AddDate(0, 0, -1)
}
if expected.Day() != date.Day() || expected.Month() != date.Month() || expected.Hour() != date.Hour() {
t.Errorf("Expected: %+v, received: %+v", expected, date)
}
}
expected = time.Now().AddDate(0, 1, 0)
if date, err := ParseTimeDetectLayout("*mo", ""); err != nil {
t.Error(err)
} else if expected.Sub(date).Seconds() > 1 {
t.Errorf("received: %+v", date)
}
expected = time.Now().AddDate(0, 1, 0).Add(time.Hour + 2*time.Minute)
if date, err := ParseTimeDetectLayout("*mo+1h2m", ""); err != nil {
t.Error(err)
} else if expected.Sub(date).Seconds() > 1 {
t.Errorf("received: %+v", date)
}
expected = time.Now().AddDate(1, 0, 0)
if date, err := ParseTimeDetectLayout("*yearly", ""); err != nil {
t.Error(err)
} else if expected.Sub(date).Seconds() > 1 {
t.Errorf("received: %+v", date)
}
expected = GetEndOfMonth(time.Now())
if date, err := ParseTimeDetectLayout("*month_end", ""); err != nil {
t.Error(err)
} else if !date.Equal(expected) {
t.Errorf("received: %+v", date)
}
expected = GetEndOfMonth(time.Now()).Add(time.Hour).Add(2 * time.Minute)
if date, err := ParseTimeDetectLayout("*month_end+1h2m", ""); err != nil {
t.Error(err)
} else if !date.Equal(expected) {
t.Errorf("expecting: %+v, received: %+v", expected, date)
}
if date, err := ParseTimeDetectLayout("*month_end+xyz", ""); err == nil {
t.Error("Expecting error 'time: invalid time duration', received: nil")
} else if date != nilTime {
t.Errorf("Expecting nilTime, received: %+v", date)
}
if date, err := ParseTimeDetectLayout("*mo+xyz", ""); err == nil {
t.Error("Expecting error 'time: invalid time duration', received: nil")
} else if date != nilTime {
t.Errorf("Expecting nilTime, received: %+v", date)
}
date, err = ParseTimeDetectLayout("2013-07-30T19:33:10Z", "")
expected = time.Date(2013, 7, 30, 19, 33, 10, 0, time.UTC)
if err != nil || !date.Equal(expected) {
t.Error("error parsing date: ", expected.Sub(date))
}
date, err = ParseTimeDetectLayout("2016-04-01T02:00:00+02:00", "")
expected = time.Date(2016, 4, 1, 0, 0, 0, 0, time.UTC)
if err != nil || !date.Equal(expected) {
t.Errorf("Expecting: %v, received: %v", expected, date)
}
date, err = ParseTimeDetectLayout("2014-11-25T00:00:00+01:00", "")
expected = time.Date(2014, 11, 24, 23, 0, 0, 0, time.UTC)
if err != nil || !date.UTC().Equal(expected.UTC()) {
t.Errorf("Expecting: %v, received: %v", expected.UTC(), date.UTC())
}
}
func TestRoundDuration(t *testing.T) {
minute := time.Minute
result := RoundDuration(minute, 0)
expected := 0 * time.Second
if result != expected {
t.Errorf("Error rounding to minute1: expected %v was %v", expected, result)
}
result = RoundDuration(time.Second, time.Second+500*time.Millisecond)
expected = 2 * time.Second
if result != expected {
t.Errorf("Error rounding to minute1: expected %v was %v", expected, result)
}
result = RoundDuration(minute, time.Second)
expected = minute
if result != expected {
t.Errorf("Error rounding to minute2: expected %v was %v", expected, result)
}
result = RoundDuration(minute, 5*time.Second)
expected = minute
if result != expected {
t.Errorf("Error rounding to minute3: expected %v was %v", expected, result)
}
result = RoundDuration(minute, minute)
expected = minute
if result != expected {
t.Errorf("Error rounding to minute4: expected %v was %v", expected, result)
}
result = RoundDuration(minute, 90*time.Second)
expected = 120 * time.Second
if result != expected {
t.Errorf("Error rounding to minute5: expected %v was %v", expected, result)
}
result = RoundDuration(60, 120)
expected = 120.0
if result != expected {
t.Errorf("Error rounding to minute5: expected %v was %v", expected, result)
}
}
func TestRoundStatDuration(t *testing.T) {
result := RoundStatDuration(time.Second+14565876*time.Nanosecond, 5)
expected := time.Second + 14570000*time.Nanosecond
if result != expected {
t.Errorf("Expected %+v, received %+v", expected, result)
}
result = RoundStatDuration(time.Second+14565876*time.Nanosecond, 1)
expected = time.Second
if result != expected {
t.Errorf("Expected %+v, received %+v", expected, result)
}
result = RoundStatDuration(time.Second+14565876*time.Nanosecond, 9)
expected = time.Second + 14565876*time.Nanosecond
if result != expected {
t.Errorf("Expected %+v, received %+v", expected, result)
}
result = RoundStatDuration(24*time.Second+14565876*time.Nanosecond, -1)
expected = 20 * time.Second
if result != expected {
t.Errorf("Expected %+v, received %+v", expected, result)
}
result = RoundStatDuration(24*time.Second+14565876*time.Nanosecond, 0)
expected = 24 * time.Second
if result != expected {
t.Errorf("Expected %+v, received %+v", expected, result)
}
}
func TestSplitPrefix(t *testing.T) {
exp := []string{"0123456789", "012345678", "01234567", "0123456", "012345", "01234", "0123", "012", "01", "0"}
if a := SplitPrefix("0123456789", 1); len(a) != 10 {
t.Error("Error splitting prefix: ", a)
} else if !reflect.DeepEqual(a, exp) {
t.Errorf("Expecting: %v, received: %v", exp, a)
}
exp = []string{"0123456789", "012345678", "01234567", "0123456", "012345", "01234"}
if a := SplitPrefix("0123456789", 5); len(a) != 6 {
t.Error("Error splitting prefix: ", a)
} else if !reflect.DeepEqual(a, exp) {
t.Errorf("Expecting: %v, received: %v", exp, a)
}
exp = []string{}
if a := SplitPrefix("", 1); len(a) != 0 {
t.Error("Error splitting prefix: ", a)
} else if !reflect.DeepEqual(a, exp) {
t.Errorf("Expecting: %v, received: %v", exp, a)
}
}
func TestSplitSuffix(t *testing.T) {
exp := []string{"9", "89", "789", "6789", "56789", "456789", "3456789", "23456789", "123456789", "0123456789"}
if a := SplitSuffix("0123456789"); len(a) != 10 {
t.Error("Error splitting prefix: ", ToJSON(a))
} else if !reflect.DeepEqual(a, exp) {
t.Errorf("Expecting: %v, received: %v", exp, a)
}
if a := SplitSuffix(""); len(a) != 0 {
t.Error("Error splitting prefix: ", a)
}
}
func TestCopyHour(t *testing.T) {
var src, dst, eOut time.Time
if rcv := CopyHour(src, dst); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
src = time.Date(2020, time.April, 18, 20, 10, 11, 01, time.UTC)
dst = time.Date(2019, time.May, 25, 23, 0, 4, 0, time.UTC)
eOut = time.Date(2019, time.May, 25, 20, 10, 11, 01, time.UTC)
if rcv := CopyHour(src, dst); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestParseDurationWithSecs(t *testing.T) {
var durExpected time.Duration
if rcv, err := ParseDurationWithSecs(""); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rcv, durExpected) {
t.Errorf("Expecting: 0s, received: %+v", rcv)
}
durStr := "2"
durExpected = 2 * time.Second
if parsed, err := ParseDurationWithSecs(durStr); err != nil {
t.Error(err)
} else if parsed != durExpected {
t.Error("Parsed different than expected")
}
durStr = "2s"
if parsed, err := ParseDurationWithSecs(durStr); err != nil {
t.Error(err)
} else if parsed != durExpected {
t.Error("Parsed different than expected")
}
durStr = "2ms"
durExpected = 2 * time.Millisecond
if parsed, err := ParseDurationWithSecs(durStr); err != nil {
t.Error(err)
} else if parsed != durExpected {
t.Error("Parsed different than expected")
}
durStr = "0.002"
durExpected = 2 * time.Millisecond
if parsed, err := ParseDurationWithSecs(durStr); err != nil {
t.Error(err)
} else if parsed != durExpected {
t.Error("Parsed different than expected")
}
durStr = "1.002"
durExpected = 1002 * time.Millisecond
if parsed, err := ParseDurationWithSecs(durStr); err != nil {
t.Error(err)
} else if parsed != durExpected {
t.Error("Parsed different than expected")
}
}
func TestParseDurationWithNanosecs(t *testing.T) {
var eOut time.Duration
if rcv, err := ParseDurationWithNanosecs(""); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
eOut, _ = time.ParseDuration("-1ns")
if rcv, err := ParseDurationWithNanosecs(MetaUnlimited); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
eOut, _ = time.ParseDuration("28ns")
if rcv, err := ParseDurationWithNanosecs("28"); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestMinDuration(t *testing.T) {
d1, _ := time.ParseDuration("1m")
d2, _ := time.ParseDuration("59s")
minD1 := MinDuration(d1, d2)
minD2 := MinDuration(d2, d1)
if minD1 != d2 || minD2 != d2 {
t.Error("Error getting min duration: ", minD1, minD2)
}
}
func TestParseZeroRatingSubject(t *testing.T) {
subj := []string{"", "*zero1024", "*zero1s", "*zero5m", "*zero10h"}
dur := []time.Duration{time.Second, 1024,
time.Second, 5 * time.Minute, 10 * time.Hour}
dfltRatingSubject := map[string]string{
MetaAny: "*zero1ns",
MetaVoice: "*zero1s",
}
for i, s := range subj {
if i == 0 {
if d, err := ParseZeroRatingSubject(MetaVoice, s, dfltRatingSubject, false); err == nil {
t.Error("Error parsing rating subject: ", s, d, err)
}
} else {
if d, err := ParseZeroRatingSubject(MetaVoice, s, dfltRatingSubject, true); err != nil || d != dur[i] {
t.Error("Error parsing rating subject: ", s, d, err)
}
}
if d, err := ParseZeroRatingSubject(MetaData, EmptyString, dfltRatingSubject, true); err != nil || d != time.Nanosecond {
t.Error("Error parsing rating subject: ", EmptyString, d, err)
}
if d, err := ParseZeroRatingSubject(MetaSMS, EmptyString, dfltRatingSubject, true); err != nil || d != time.Nanosecond {
t.Error("Error parsing rating subject: ", EmptyString, d, err)
}
if d, err := ParseZeroRatingSubject(MetaMMS, EmptyString, dfltRatingSubject, true); err != nil || d != time.Nanosecond {
t.Error("Error parsing rating subject: ", EmptyString, d, err)
}
if d, err := ParseZeroRatingSubject(MetaMonetary, EmptyString, dfltRatingSubject, true); err != nil || d != time.Nanosecond {
t.Error("Error parsing rating subject: ", EmptyString, d, err)
}
expecting := "malformed rating subject: test"
if _, err := ParseZeroRatingSubject(MetaMonetary, "test", dfltRatingSubject, true); err == nil || err.Error() != expecting {
t.Errorf("Expecting: %+v, received: %+v ", expecting, err)
}
}
}
func TestConcatenatedKey(t *testing.T) {
if key := ConcatenatedKey("a"); key != "a" {
t.Error("Unexpected key value received: ", key)
}
if key := ConcatenatedKey("a", "b"); key != fmt.Sprintf("a%sb", ConcatenatedKeySep) {
t.Error("Unexpected key value received: ", key)
}
if key := ConcatenatedKey("a", "b", "c"); key != fmt.Sprintf("a%sb%sc", ConcatenatedKeySep, ConcatenatedKeySep) {
t.Error("Unexpected key value received: ", key)
}
}
func TestSplitConcatenatedKey(t *testing.T) {
key := "test1:test2:test3"
eOut := []string{"test1", "test2", "test3"}
if rcv := SplitConcatenatedKey(key); !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestInfieldJoin(t *testing.T) {
if rcv := InfieldJoin(""); rcv != "" {
t.Errorf("Expecting: empty string, received: %+v", ToJSON(rcv))
}
key := "test1;test2;test3"
eOut := "test1;test2;test3"
if rcv := InfieldJoin(key); !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", ToJSON(eOut), ToJSON(rcv))
}
key2 := "test10;test12"
eOut = "test1;test2;test3;test10;test12"
if rcv := InfieldJoin(key, key2); !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", ToJSON(eOut), ToJSON(rcv))
}
}
func TestInfieldSplit(t *testing.T) {
key := "test1;test2;test3"
eOut := []string{"test1", "test2", "test3"}
if rcv := InfieldSplit(key); !reflect.DeepEqual(eOut, rcv) {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
}
func TestFmtFieldWidth(t *testing.T) {
//Mandatory0
if _, err := FmtFieldWidth("", "", 0, "", "", true); err == nil {
t.Errorf("Failed to detect mandatory value")
}
//width = 0
if result, err := FmtFieldWidth("", "test", 0, "", "", false); err != nil {
t.Error(err)
} else if result != "test" {
t.Errorf("Expecting 'test', received %+q", result)
}
//MaxLen
if result, err := FmtFieldWidth("", "test", 4, "", "", false); err != nil {
t.Error(err)
} else if result != "test" {
t.Errorf("Expected \"test\" received: \"%s\"", result)
}
//RPadding
if result, err := FmtFieldWidth("", "test", 8, "", "*right", false); err != nil {
t.Error(err)
} else if result != "test " {
t.Errorf("Expected <\"test \"> \" received: \"%s\"", result)
}
//PaddingFiller
expected := " "
if result, err := FmtFieldWidth("", "", 8, "", "*right", false); err != nil {
t.Error(err)
} else if result != expected {
t.Errorf("Expected \"%s \" received: \"%s\"", expected, result)
}
//LPadding
expected = " test"
if result, err := FmtFieldWidth("", "test", 8, "", "*left", false); err != nil {
t.Error(err)
} else if result != expected {
t.Errorf("Expected \"%s \" received: \"%s\"", expected, result)
}
//ZeroLPadding
expected = "0000test"
if result, err := FmtFieldWidth("", "test", 8, "", "*zeroleft", false); err != nil {
t.Error(err)
} else if result != expected {
t.Errorf("Expected \"%s \" received: \"%s\"", expected, result)
}
//RStrip
expected = "te"
if result, err := FmtFieldWidth("", "test", 2, "*right", "", false); err != nil {
t.Error(err)
} else if result != expected {
t.Errorf("Expected \"%s \" received: \"%s\"", expected, result)
}
//XRStrip
expected = "tex"
if result, err := FmtFieldWidth("", "test", 3, "*xright", "", false); err != nil {
t.Error(err)
} else if result != expected {
t.Errorf("Expected \"%s \" received: \"%s\"", expected, result)
}
//LStrip
expected = "st"
if result, err := FmtFieldWidth("", "test", 2, "*left", "", false); err != nil {
t.Error(err)
} else if result != expected {
t.Errorf("Expected \"%s \" received: \"%s\"", expected, result)
}
//XLStrip
expected = "xst"
if result, err := FmtFieldWidth("", "test", 3, "*xleft", "", false); err != nil {
t.Error(err)
} else if result != expected {
t.Errorf("Expected \"%s \" received: \"%s\"", expected, result)
}
//StripNotAllowed
if _, err := FmtFieldWidth("", "test", 3, "", "", false); err == nil {
t.Error("Expected error")
}
//PaddingNotAllowed
if _, err := FmtFieldWidth("", "test", 5, "", "", false); err == nil {
t.Error("Expected error")
}
//
expected = "test"
if result, err := FmtFieldWidth("", "test", 3, "wrong", "", false); err != nil {
t.Error(err)
} else if result != expected {
t.Errorf("Expected \"%s \" received: \"%s\"", expected, result)
}
}
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)
if !eom.Equal(expected) {
t.Errorf("Expected %v was %v", expected, eom)
}
eom = GetEndOfMonth(time.Date(2015, time.February, 5, 10, 1, 2, 3, time.UTC))
expected = time.Date(2015, time.February, 28, 23, 59, 59, 0, time.UTC)
if !eom.Equal(expected) {
t.Errorf("Expected %v was %v", expected, eom)
}
eom = GetEndOfMonth(time.Date(2016, time.January, 31, 10, 1, 2, 3, time.UTC))
expected = time.Date(2016, time.January, 31, 23, 59, 59, 0, time.UTC)
if !eom.Equal(expected) {
t.Errorf("Expected %v was %v", expected, eom)
}
eom = GetEndOfMonth(time.Date(2016, time.December, 31, 10, 1, 2, 3, time.UTC))
expected = time.Date(2016, time.December, 31, 23, 59, 59, 0, time.UTC)
if !eom.Equal(expected) {
t.Errorf("Expected %v was %v", expected, eom)
}
eom = GetEndOfMonth(time.Date(2016, time.July, 31, 23, 59, 59, 0, time.UTC))
expected = time.Date(2016, time.July, 31, 23, 59, 59, 0, time.UTC)
if !eom.Equal(expected) {
t.Errorf("Expected %v was %v", expected, eom)
}
// Date ref represents zero time instant, will return time.Now().
eom = GetEndOfMonth(time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC))
if currentDateRef := time.Now(); currentDateRef.Before(eom) ||
time.Since(eom) > time.Millisecond {
t.Errorf("Expected GetEndOfMonth to return the current date info, received: %s", eom)
}
}
func TestSizeFmt(t *testing.T) {
if str := SizeFmt(0, EmptyString); str != "0.0B" {
t.Errorf("Expecting: 0.0B, received: %+q", str)
}
if str := SizeFmt(1023, EmptyString); str != "1023.0B" {
t.Errorf("Expecting: 1023.0B, received: %+q", str)
}
if str := SizeFmt(1024, EmptyString); str != "1.0KiB" {
t.Errorf("Expecting: 1.0KiB, received: %+q", str)
}
if str := SizeFmt(1048575, EmptyString); str != "1024.0KiB" {
t.Errorf("Expecting: 1024.0KiB, received: %+q", str)
}
if str := SizeFmt(1048576, EmptyString); str != "1.0MiB" {
t.Errorf("Expecting: 1.0MiB, received: %+q", str)
}
if str := SizeFmt(1073741823, EmptyString); str != "1024.0MiB" {
t.Errorf("Expecting: 1024.0MiB, received: %+q", str)
}
if str := SizeFmt(1073741824, EmptyString); str != "1.0GiB" {
t.Errorf("Expecting: 1.0GiB, received: %+q", str)
}
if str := SizeFmt(1099511627775, EmptyString); str != "1024.0GiB" {
t.Errorf("Expecting: 1024.0GiB, received: %+q", str)
}
if str := SizeFmt(1099511627776, EmptyString); str != "1.0TiB" {
t.Errorf("Expecting: 1.0TiB, received: %+q", str)
}
if str := SizeFmt(1125899906842623, EmptyString); str != "1024.0TiB" {
t.Errorf("Expecting: 1024.0TiB, received: %+q", str)
}
if str := SizeFmt(1125899906842624, EmptyString); str != "1.0PiB" {
t.Errorf("Expecting: 1.0PiB, received: %+q", str)
}
if str := SizeFmt(1152921504606847000, EmptyString); str != "1.0EiB" {
t.Errorf("Expecting: 1.0EiB, received: %+q", str)
}
if str := SizeFmt(1180591620717411303424, EmptyString); str != "1.0ZiB" {
t.Errorf("Expecting: 1.0ZiB, received: %+q", str)
}
if str := SizeFmt(9000000000000000000000000, EmptyString); str != "7.4YiB" {
t.Errorf("Expecting: 7.4YiB, received: %+q", str)
}
}
func TestParseHierarchyPath(t *testing.T) {
eHP := HierarchyPath([]string{"Root", "CGRateS"})
if hp := ParseHierarchyPath("/Root/CGRateS/", ""); !reflect.DeepEqual(hp, eHP) {
t.Errorf("Expecting: %+v, received: %+v", eHP, hp)
}
if hp := ParseHierarchyPath("Root.CGRateS", ""); !reflect.DeepEqual(hp, eHP) {
t.Errorf("Expecting: %+v, received: %+v", eHP, hp)
}
}
func TestHierarchyPathAsString(t *testing.T) {
tests := []struct {
name string
hP HierarchyPath
sep string
prefix bool
expected string
}{
{
name: "Empty HierarchyPath without prefix",
hP: HierarchyPath{},
sep: "/",
prefix: false,
expected: "",
},
{
name: "Empty HierarchyPath with prefix",
hP: HierarchyPath{},
sep: "/",
prefix: true,
expected: "/",
},
{
name: "Single element without prefix",
hP: HierarchyPath{"element"},
sep: "/",
prefix: false,
expected: "element",
},
{
name: "Single element with prefix",
hP: HierarchyPath{"element"},
sep: "/",
prefix: true,
expected: "/element",
},
{
name: "Multiple elements without prefix",
hP: HierarchyPath{"a", "b", "c"},
sep: "/",
prefix: false,
expected: "a/b/c",
},
{
name: "Multiple elements with prefix",
hP: HierarchyPath{"a", "b", "c"},
sep: "/",
prefix: true,
expected: "/a/b/c",
},
{
name: "Custom separator without prefix",
hP: HierarchyPath{"a", "b", "c"},
sep: "->",
prefix: false,
expected: "a->b->c",
},
{
name: "Custom separator with prefix",
hP: HierarchyPath{"a", "b", "c"},
sep: "->",
prefix: true,
expected: "->a->b->c",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if received := tt.hP.AsString(tt.sep, tt.prefix); received != tt.expected {
t.Errorf("expected %s, received %s", tt.expected, received)
}
})
}
}
func TestParseHierarchyClone(t *testing.T) {
eHP := HierarchyPath([]string{"Root", "CGRateS"})
rcv := eHP.Clone()
if !reflect.DeepEqual(eHP, rcv) {
t.Errorf("Expected: %+v\nReceived: %+v", ToJSON(eHP), ToJSON(rcv))
}
if rcv[0] = ""; eHP[0] != "Root" {
t.Errorf("Expected clone to not modify the cloned")
}
eHP = nil
rcv = eHP.Clone()
if !reflect.DeepEqual(eHP, rcv) {
t.Errorf("Expected: %+v\nReceived: %+v", ToJSON(eHP), ToJSON(rcv))
}
}
func TestMaskSuffix(t *testing.T) {
dest := "+4986517174963"
if destMasked := MaskSuffix(dest, 3); destMasked != "+4986517174***" {
t.Error("Unexpected mask applied", destMasked)
}
if destMasked := MaskSuffix(dest, -1); destMasked != dest {
t.Error("Negative maskLen should not modify destination", destMasked)
}
if destMasked := MaskSuffix(dest, 0); destMasked != dest {
t.Error("Zero maskLen should not modify destination", destMasked)
}
if destMasked := MaskSuffix(dest, 100); destMasked != "**************" {
t.Error("High maskLen should return complete mask", destMasked)
}
}
func TestTimeIs0h(t *testing.T) {
t1, err := time.Parse(time.RFC3339, "2012-11-01T22:08:41+00:00")
if err != nil {
t.Error("time parsing error")
}
result := TimeIs0h(t1)
if result != false {
t.Error("time is 0 when it's supposed to be", t1)
}
}
func TestToJSON(t *testing.T) {
if outNilObj := ToJSON(nil); outNilObj != "null" {
t.Errorf("Expecting null, received: <%q>", outNilObj)
}
}
func TestClone(t *testing.T) {
a := 15
var b int
err := Clone(a, &b)
if err != nil {
t.Error("Cloning failed")
}
if b != a {
t.Error("Expected:", a, ", received:", b)
}
// Clone from an interface
c := "mystr"
ifaceC := any(c)
clndIface := reflect.Indirect(reflect.New(reflect.TypeOf(ifaceC))).Interface().(string)
if err := Clone(ifaceC, &clndIface); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(ifaceC, clndIface) {
t.Errorf("Expecting: %+v, received: %+v", ifaceC, clndIface)
}
if err := Clone(math.NaN, nil); err == nil {
t.Error("Expected error")
}
}
func TestFib(t *testing.T) {
fib := Fib()
if tmp := fib(); tmp != 1 {
t.Error("Expecting: 1s, received ", tmp)
}
if tmp := fib(); tmp != 1 {
t.Error("Expecting: 1s, received ", tmp)
}
if tmp := fib(); tmp != 2 {
t.Error("Expecting: 2s, received ", tmp)
}
if tmp := fib(); tmp != 3 {
t.Error("Expecting: 3s, received ", tmp)
}
if tmp := fib(); tmp != 5 {
t.Error("Expecting: 5s, received ", tmp)
}
}
func TestStringPointer(t *testing.T) {
result := StringPointer("*zero")
if *result != EmptyString {
t.Errorf("Expecting: `%+q`, received `%+q`", EmptyString, *result)
}
str := "test_string"
result = StringPointer(str)
expected := &str
if *result != *expected {
t.Errorf("Expecting: %+v, received: %+v", &str, result)
}
}
func TestIntPointer(t *testing.T) {
t1 := 14
result := IntPointer(t1)
expected := &t1
if *expected != *result {
t.Errorf("Expecting: %+v, received: %+v", expected, result)
}
}
func TestInt64Pointer(t *testing.T) {
var t1 int64 = 19
result := Int64Pointer(t1)
expected := &t1
if *expected != *result {
t.Error("Expected:", expected, ", received:", result)
}
}
func TestFloat64Pointer(t *testing.T) {
var t1 float64 = 11.5
result := Float64Pointer(t1)
expected := &t1
if *expected != *result {
t.Error("Expected:", expected, ", received:", result)
}
}
func TestBoolPointer(t *testing.T) {
t1 := true
result := BoolPointer(t1)
expected := &t1
if *expected != *result {
t.Error("Expected:", expected, ", received:", result)
}
}
func TestStringMapPointer(t *testing.T) {
t1 := map[string]bool{"cgr1": true, "cgr2": true}
expected := &t1
result := StringMapPointer(t1)
if *result == nil {
t.Error("Expected:", expected, ", received: nil")
}
}
func TestMapStringStringPointer(t *testing.T) {
mp := map[string]string{"string1": "string2"}
result := MapStringStringPointer(mp)
expected := &mp
if *result == nil {
t.Errorf("Expected: %+q, received: nil", expected)
}
}
func TestTimePointer(t *testing.T) {
t1, err := time.Parse(time.RFC3339, "2012-11-01T22:08:41+00:00")
if err != nil {
t.Error("time parsing error")
}
result := TimePointer(t1)
expected := &t1
if *expected != *result {
t.Error("Expected:", expected, ", received:", result)
}
}
func TestDurationPointer(t *testing.T) {
duration := 10 * time.Nanosecond
result := DurationPointer(duration)
expected := &duration
if *expected != *result {
t.Errorf("Expected: %+q, received: %+q", expected, result)
}
}
func TestSliceStringPointer(t *testing.T) {
sl := []string{"test"}
result := SliceStringPointer(sl)
exp := result
if !reflect.DeepEqual(result, exp) {
t.Errorf("Expeced:%+q but received %+q", exp, result)
}
}
func TestToIJSON(t *testing.T) {
str := "string"
received := ToIJSON(str)
expected := "\"string\""
if !reflect.DeepEqual(received, expected) {
t.Errorf("Expected: %+q, received: %+q", expected, received)
}
}
func TestLen(t *testing.T) {
t1 := Int64Slice{2112443, 414241412, 41231241}
result := t1.Len()
expected := 3
if result != expected {
t.Error("Expected:", expected, ", received:", result)
}
}
func TestSwap(t *testing.T) {
t1 := Int64Slice{414241412, 41231241}
t1.Swap(0, 1)
var expected int64 = 414241412
if t1[1] != expected {
t.Error("Expected:", expected, ", received:", t1[1])
}
}
func TestLess(t *testing.T) {
t1 := Int64Slice{414241412, 41231241}
expected := false
if t1.Less(0, 1) != expected {
t.Error("Expected:", expected, ", received:", t1.Less(1, 2))
}
}
func TestGetCGRVersion(t *testing.T) {
GitLastLog = `commit 73014daa0c1d7edcb532d5fe600b8a20d588cdf8
Author: DanB <danb@cgrates.org>
AuthorDate: Fri Dec 30 19:48:09 2016 +0100
Commit: DanB <danb@cgrates.org>
CommitDate: Fri Dec 30 19:48:09 2016 +0100
Fixes for db driver to avoid returning new values in case of errors
`
expVers := "CGRateS@" + Version
eVers := expVers + "-20161230184809-73014daa0c1d"
if vers, err := GetCGRVersion(); err != nil {
t.Error(err)
} else if vers != eVers {
t.Errorf("Expecting: <%s>, received: <%s>", eVers, vers)
}
GitLastLog = ""
if vers, err := GetCGRVersion(); err != nil {
t.Error(err)
} else if vers != expVers {
t.Errorf("Expecting: <%s>, received: <%s>", expVers, vers)
}
GitLastLog = "\n"
if vers, err := GetCGRVersion(); err == nil || err.Error() != "Building version - error: <EOF> reading line from file" {
t.Error(err)
} else if vers != expVers {
t.Errorf("Expecting: <%s>, received: <%s>", expVers, vers)
}
GitLastLog = `commit . . .
`
if vers, err := GetCGRVersion(); err == nil || err.Error() != "Building version - cannot extract commit hash" {
t.Error(err)
} else if vers != expVers {
t.Errorf("Expecting: <%s>, received: <%s>", expVers, vers)
}
GitLastLog = `CommitDate: : :
`
if vers, err := GetCGRVersion(); err == nil || err.Error() != "Building version - cannot split commit date" {
t.Error(err)
} else if vers != expVers {
t.Errorf("Expecting: <%s>, received: <%s>", expVers, vers)
}
GitLastLog = `CommitDate: wrong format
`
if vers, err := GetCGRVersion(); err == nil || err.Error() != `Building version - error: <parsing time "wrong format" as "Mon Jan 2 15:04:05 2006 -0700": cannot parse "wrong format" as "Mon"> compiling commit date` {
t.Error(err)
} else if vers != expVers {
t.Errorf("Expecting: <%s>, received: <%s>", expVers, vers)
}
GitLastLog = `ommit 73014daa0c1d7edcb532d5fe600b8a20d588cdf8
Author: DanB <danb@cgrates.org>
Date: Fri Dec 30 19:48:09 2016 +0100
Fixes for db driver to avoid returning new values in case of errors
`
if vers, err := GetCGRVersion(); err == nil || err.Error() != "Cannot find commitHash or commitDate information" {
t.Error(err)
} else if vers != expVers {
t.Errorf("Expecting: <%s>, received: <%s>", expVers, vers)
}
GitLastLog = `commit c34d5753cf5ae15a3b7ae9bea30a4900fb8191a0
Author: nickolasdaniel <nickolas.filip@itsyscom.com>
AuthorDate: Wed Feb 2 16:54:59 2022 +0200
Commit: nickolasdaniel <nickolas.filip@itsyscom.com>
CommitDate: Wed Feb 2 16:54:59 2022 +0200
Changed the build script and GetCGRVersion() to get the CommitDate instead of AuthorDate
`
expVers = "CGRateS@" + Version
eVers = expVers + "-20220202145459-c34d5753cf5a"
if vers, err := GetCGRVersion(); err != nil {
t.Error(err)
} else if vers != eVers {
t.Errorf("Expecting: <%s>, received: <%s>", eVers, vers)
}
GitLastLog = `commit c34d5753cf5ae15a3b7ae9bea30a4900fb8191a0
Author: nickolasdaniel <nickolas.filip@itsyscom.com>
AuthorDate: Thu Jun 5 12:14:49 2026 +0800
Commit: nickolasdaniel <nickolas.filip@itsyscom.com>
CommitDate: Wed Feb 2 16:54:59 2022 +0200
Changed the build script and GetCGRVersion() to get the CommitDate instead of AuthorDate
`
expVers = "CGRateS@" + Version
eVers = expVers + "-20220202145459-c34d5753cf5a"
if vers, err := GetCGRVersion(); err != nil {
t.Error(err)
} else if vers != eVers {
t.Errorf("Expecting: <%s>, received: <%s>", eVers, vers)
}
}
func TestNewTenantID(t *testing.T) {
eOut := &TenantID{ID: EmptyString}
if rcv := NewTenantID(EmptyString); *rcv != *eOut {
t.Errorf("Expecting: %+v, received %+v", eOut, rcv)
}
eOut = &TenantID{Tenant: "Test"}
if rcv := NewTenantID("Test:"); *rcv != *eOut {
t.Errorf("Expecting: %+v, received %+v", eOut, rcv)
}
eOut = &TenantID{Tenant: "cgrates.org", ID: "id"}
if rcv := NewTenantID("cgrates.org:id"); *rcv != *eOut {
t.Errorf("Expecting: %+v, received %+v", eOut, rcv)
}
}
func TestTenantID(t *testing.T) {
tID := &TenantID{Tenant: EmptyString, ID: EmptyString}
eOut := ":"
if rcv := tID.TenantID(); rcv != eOut {
t.Errorf("Expecting: %q, received: %q", eOut, rcv)
}
tID = &TenantID{Tenant: "cgrates.org", ID: "id"}
eOut = "cgrates.org:id"
if rcv := tID.TenantID(); rcv != eOut {
t.Errorf("Expecting: %q, received: %q", eOut, rcv)
}
}
func TestTenantIDWithCache(t *testing.T) {
tID := &TenantIDWithAPIOpts{TenantID: &TenantID{Tenant: EmptyString, ID: EmptyString}}
eOut := ":"
if rcv := tID.TenantID.TenantID(); rcv != eOut {
t.Errorf("Expecting: %q, received: %q", eOut, rcv)
}
tID = &TenantIDWithAPIOpts{TenantID: &TenantID{Tenant: "cgrates.org", ID: "id"}}
eOut = "cgrates.org:id"
if rcv := tID.TenantID.TenantID(); rcv != eOut {
t.Errorf("Expecting: %q, received: %q", eOut, rcv)
}
}
type TestRPC struct {
}
func (tRPC *TestRPC) V1Copy(args *string, reply *string) error {
*reply = *args
return nil
}
func (tRPC *TestRPC) V1Error(args *string, reply *string) error {
return errors.New("V1_err_test")
}
func (tRPC *TestRPC) Call(args any, reply any) error {
return nil
}
func (tRPC *TestRPC) V1Error2(args any, reply any) (int, error) {
return 0, nil
}
func (tRPC *TestRPC) V1Error3(args any, reply any) int {
return 0
}
func TestRPCCall(t *testing.T) {
if err := RPCCall("wrong", "test", nil, nil); err == nil || err != rpcclient.ErrUnsupporteServiceMethod {
t.Errorf("Expecting: %+v, received: %+v", rpcclient.ErrUnsupporteServiceMethod, err)
}
var reply string
if err := RPCCall(&TestRPC{}, "TestRPCV1.Copy", StringPointer("test"), &reply); err != nil {
t.Errorf("Expecting: <nil>, received: %+v", err)
}
if err := RPCCall(&TestRPC{}, "TestRPCV1.Error", StringPointer("test"), &reply); err == nil || err.Error() != "V1_err_test" {
t.Errorf("Expecting: <V1_err_test>, received: <%+v>", err)
}
if err := RPCCall(&TestRPC{}, "TestRPCV1.Unexist", StringPointer("test"), &reply); err == nil || err != rpcclient.ErrUnsupporteServiceMethod {
t.Errorf("Expecting: %+v, received: %+v", rpcclient.ErrUnsupporteServiceMethod, err)
}
if err := RPCCall(&TestRPC{}, "TestRPCV1.Error2", StringPointer("test"), &reply); err == nil || err != ErrServerError {
t.Errorf("Expecting: %+v, received: %+v", ErrServerError, err)
}
if err := RPCCall(&TestRPC{}, "TestRPCV1.Error3", StringPointer("test"), &reply); err == nil || err != ErrServerError {
t.Errorf("Expecting: %+v, received: %+v", ErrServerError, err)
}
}
type TestRPC2 struct {
}
func (tRPC *TestRPC2) Copy(args *string, reply *string) error {
*reply = *args
return nil
}
func (tRPC *TestRPC2) Error(args *string, reply *string) error {
return errors.New("V1_err_test")
}
func (tRPC *TestRPC2) Call(args any, reply any) error {
return nil
}
func (tRPC *TestRPC2) Error2(args any, reply any) (int, error) {
return 0, nil
}
func (tRPC *TestRPC2) Error3(args any, reply any) int {
return 0
}
func TestRPCAPICall(t *testing.T) {
if err := APIerRPCCall("wrong", "test", nil, nil); err == nil || err != rpcclient.ErrUnsupporteServiceMethod {
t.Errorf("Expecting: %+v, received: %+v", rpcclient.ErrUnsupporteServiceMethod, err)
}
var reply string
if err := APIerRPCCall(&TestRPC2{}, "TestRPC2.Copy", StringPointer("test"), &reply); err != nil {
t.Errorf("Expecting: <nil>, received: %+v", err)
}
if err := APIerRPCCall(&TestRPC2{}, "TestRPC2.Error", StringPointer("test"), &reply); err == nil || err.Error() != "V1_err_test" {
t.Errorf("Expecting: <V1_err_test>, received: <%+v>", err)
}
if err := APIerRPCCall(&TestRPC2{}, "TestRPC2.Unexist", StringPointer("test"), &reply); err == nil || err != rpcclient.ErrUnsupporteServiceMethod {
t.Errorf("Expecting: %+v, received: %+v", rpcclient.ErrUnsupporteServiceMethod, err)
}
if err := APIerRPCCall(&TestRPC2{}, "TestRPC2.Error2", StringPointer("test"), &reply); err == nil || err != ErrServerError {
t.Errorf("Expecting: %+v, received: %+v", ErrServerError, err)
}
if err := APIerRPCCall(&TestRPC2{}, "TestRPC2.Error3", StringPointer("test"), &reply); err == nil || err != ErrServerError {
t.Errorf("Expecting: %+v, received: %+v", ErrServerError, err)
}
}
func TestCounter(t *testing.T) {
var cmax int64 = 10000
var i int64
cnter := NewCounter(0, cmax)
for i = 1; i <= cmax; i++ {
if i != cnter.Next() {
t.Error("Counter has unexpected value")
}
}
if cnter.Next() != 0 {
t.Error("Counter did not reset")
}
}
func TestCounterConcurrent(t *testing.T) {
var nmax int64 = 10000
ch := make(chan int64, nmax)
wg := new(sync.WaitGroup)
cnter := NewCounter(0, nmax-1)
var i int64
for i = 1; i <= nmax; i++ {
wg.Add(1)
go func() {
ch <- cnter.Next()
wg.Done()
}()
}
wg.Wait()
m := make(map[int64]bool)
for i = 1; i <= nmax; i++ {
m[<-ch] = true
}
for i = 1; i <= nmax-1; i++ {
if !m[i] {
t.Errorf("Missing value: %d", i)
}
}
if cnter.Value() != 0 {
t.Error("Counter was not reseted to 0")
}
}
func TestReverseString(t *testing.T) {
if rcv := ReverseString(EmptyString); rcv != EmptyString {
t.Errorf("Expecting <%+q>, received: <%+q>", EmptyString, rcv)
}
if rcv := ReverseString("test"); rcv != "tset" {
t.Errorf("Expecting <tset>, received: <%+q>", rcv)
}
}
func TestGetUrlRawArguments(t *testing.T) {
eOut := map[string]string{}
if rcv := GetUrlRawArguments(EmptyString); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expectinc: %+v, received: %+v", eOut, rcv)
}
if rcv := GetUrlRawArguments("test"); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expectinc: %+v, received: %+v", eOut, rcv)
}
if rcv := GetUrlRawArguments("test?"); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expectinc: %+v, received: %+v", eOut, rcv)
}
eOut = map[string]string{"test": "1"}
if rcv := GetUrlRawArguments("?test=1"); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expectinc: %+v, received: %+v", eOut, rcv)
}
eOut = map[string]string{"test": "1", "test2": "2"}
if rcv := GetUrlRawArguments("?test=1&test2=2"); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expectinc: %+v, received: %+v", eOut, rcv)
}
eOut = map[string]string{"test": "1", "test2": "2", EmptyString: "5"}
if rcv := GetUrlRawArguments("?test=1&test2=2&=5"); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expectinc: %+v, received: %+v", eOut, rcv)
}
eOut = map[string]string{"test": "1", "test2": "2"}
if rcv := GetUrlRawArguments("?test=1&test2=2&5"); !reflect.DeepEqual(rcv, eOut) {
t.Errorf("Expectinc: %+v, received: %+v", eOut, rcv)
}
}
func TestWarnExecTime(t *testing.T) {
//without Log
WarnExecTime(time.Now(), "MyTestFunc", time.Second)
//With Log
WarnExecTime(time.Now(), "MyTestFunc", time.Nanosecond)
}
func TestCastRPCErr(t *testing.T) {
err := errors.New("test")
if rcv := CastRPCErr(err); rcv != err {
t.Errorf("Expecting: %+q, received %+q", err, rcv)
}
if rcv := CastRPCErr(ErrNoMoreData); rcv.Error() != ErrNoMoreData.Error() {
t.Errorf("Expecting: %+v, received %+v", ErrNoMoreData.Error(), rcv)
}
}
func TestRandomInteger(t *testing.T) {
a := RandomInteger(0, 100)
b := RandomInteger(0, 100)
c := RandomInteger(0, 100)
if a == b && b == c {
t.Errorf("same result over 3 attempts")
}
if a >= 100 || b >= 100 || c >= 100 {
t.Errorf("one of the numbers equals or it's above the max limit")
}
if a < 0 || b < 0 || c < 0 {
t.Errorf("one of the numbers are below min limit")
}
}
func TestGetPathIndex(t *testing.T) {
if rcv, _ := GetPathIndex(EmptyString); rcv != EmptyString {
t.Errorf("Expecting: \"\"(EmptyString), received: \"%+v\"", rcv)
}
eOut := "test"
if rcv, _ := GetPathIndex("test"); rcv != eOut {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
}
if rcv, index := GetPathIndex("test[10]"); rcv != eOut {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
} else if *index != 10 {
t.Errorf("Expecting: %+v, received: %+v", 10, *index)
}
if rcv, index := GetPathIndex("test[0]"); rcv != eOut {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
} else if *index != 0 {
t.Errorf("Expecting: %+v, received: %+v", 0, *index)
}
eOut = "test[notanumber]"
if rcv, index := GetPathIndex("test[notanumber]"); rcv != eOut {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
} else if index != nil {
t.Errorf("Expecting: nil, received: %+v", *index)
}
eOut = "test[]"
if rcv, index := GetPathIndex("test[]"); rcv != eOut {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
} else if index != nil {
t.Errorf("Expecting: nil, received: %+v", *index)
}
eOut = "[]"
if rcv, index := GetPathIndex("[]"); rcv != eOut {
t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
} else if index != nil {
t.Errorf("Expecting: nil, received: %+v", *index)
}
}
func TestIsURL(t *testing.T) {
urls := map[string]bool{
"/etc/usr/": false,
"https://github.com/cgrates/cgrates/": true,
"http://github.com/cgrates/cgrates/i": true,
}
for url, expected := range urls {
if rply := IsURL(url); rply != expected {
t.Errorf("For: %q ,expected %v received: %v", url, expected, rply)
}
}
}
func TestComputeHashMatch(t *testing.T) {
lns, _ := ComputeHash("test1;test2;test3")
if err := VerifyHash(lns, "test1;test2;test3"); err != true {
t.Errorf("Expected <true> received: <%v>", err)
}
}
func TestVerifyHash(t *testing.T) {
lns, _ := ComputeHash("test1;test2;test3")
lns2, _ := ComputeHash("test1;test2;test3")
verify1 := VerifyHash(lns, "test1;test2;test3")
verify2 := bcrypt.CompareHashAndPassword([]byte(lns2), []byte(ConcatenatedKey("test1;test2;test3")))
verify3 := false
if verify2 == nil {
verify3 = true
}
if !reflect.DeepEqual(verify3, verify1) {
t.Errorf("Expecting: <%+v>, received: <%+v>", verify3, verify1)
}
}
func TestAESEncryptErrorNil(t *testing.T) {
encKey := "6368616e676520746869732070617373776f726420746f206120736563726574"
_, err := AESEncrypt("exampleText", encKey)
if err != nil {
t.Errorf("Expecting: <nil>, received: <%+v>", err)
}
}
func TestAESEncryptError1(t *testing.T) {
encKey := "1"
_, err := AESEncrypt("exampleText", encKey)
if err == nil || err.Error() != "crypto/aes: invalid key size 0" {
t.Errorf("Expecting error: <crypto/aes: invalid key size 0>, received: <%+v>", err)
}
}
func TestAESDecryptErrorNil(t *testing.T) {
encKey := "6368616e676520746869732070617373776f726420746f206120736563726574"
eString, _ := AESEncrypt("exampleText", encKey)
_, err := AESDecrypt(eString, encKey)
if err != nil {
t.Errorf("Expecting: <nil>, received: <%+v>", err)
}
}
func TestAESDecryptError1(t *testing.T) {
encKey := "1"
eString, _ := AESEncrypt("exampleText", encKey)
_, err := AESDecrypt(eString, encKey)
if err == nil || err.Error() != "crypto/aes: invalid key size 0" {
t.Errorf("Expecting: <crypto/aes: invalid key size 0>, received: <%+v>", err)
}
}
func TestAESEncryptDecrypt(t *testing.T) {
encKey := "6368616e676520746869732070617373776f726420746f206120736563726574"
eString, _ := AESEncrypt("exampleText", encKey)
dString, _ := AESDecrypt(eString, encKey)
if !reflect.DeepEqual("exampleText", dString) {
t.Errorf("Expecting: <exampleText>, received: <%+v>", dString)
}
}
func TestBoolGenerator(t *testing.T) {
boolTest := BoolGenerator().RandomBool()
if boolTest != true && boolTest != false {
t.Errorf("Needs to be bool")
}
}
func TestMonthlyEstimated(t *testing.T) {
t1 := time.Date(2021, 1, 31, 0, 0, 0, 0, time.UTC)
expectedTime := time.Date(2021, 2, 28, 0, 0, 0, 0, time.UTC)
if rcv, err := monthlyEstimated(t1); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rcv, expectedTime) {
t.Errorf("Expected %+v, received %+v", expectedTime, rcv)
}
}
type server struct{}
type client struct{}
func (c client) Call(serviceMethod string, args any, reply any) (err error) {
err = ErrExists
return
}
func (srv *server) BiRPCv1ValidMethod(cl birpc.ClientConnector, args any, req any) error {
return nil
}
func (srv *server) BiRPCv1MultipleParams(cl birpc.ClientConnector, args any, req any) (int, error) {
return 1, nil
}
func (srv *server) BiRPCv1NoErrorReturn(cl birpc.ClientConnector, args any, req any) int {
return 1
}
func (srv *server) BiRPCv1FinalError(cl birpc.ClientConnector, args any, req any) (err error) {
err = ErrExists
return
}
func TestCoreUtilsGenerateDBItemOpts(t *testing.T) {
apiKey := "testKey1"
routeID := "testKey2"
cache := "testKey3"
rmtHost := "testKey4"
expected := map[string]any{
OptsAPIKey: apiKey,
OptsRouteID: routeID,
CacheOpt: cache,
RemoteHostOpt: rmtHost,
}
received := GenerateDBItemOpts(apiKey, routeID, cache, rmtHost)
if len(received) != len(expected) {
t.Fatalf("The maps differ in length")
}
for key, value := range received {
if expected[key] != value {
t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", expected[key], value)
}
}
}
func TestTenantIDConcatenated(t *testing.T) {
tnt := &TenantID{
Tenant: "cgrates.org",
ID: "1",
}
tntOpts := &TenantIDWithAPIOpts{
TenantID: tnt,
}
rcvExpect := "cgrates.org:1"
concTnt := tntOpts.TenantIDConcatenated()
if concTnt != rcvExpect {
t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", rcvExpect, concTnt)
}
}
func TestCoreUtilsSplitPath(t *testing.T) {
exp := []string{"*string", "~*req.Account", "1001"}
if rcv := SplitPath("*string:~*req.Account:1001",
InInFieldSep[0], -1); !reflect.DeepEqual(rcv, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv)
}
exp = []string{"~*req", "Account"}
if rcv := SplitPath("~*req.Account", NestingSep[0], -1); !reflect.DeepEqual(rcv, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv)
}
exp = []string{"*exists", "~*vars.*processedProfileIDs[cgrates.org:ATTR]", ""}
if rcv := SplitPath("*exists:~*vars.*processedProfileIDs[cgrates.org:ATTR]:",
InInFieldSep[0], -1); !reflect.DeepEqual(rcv, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv)
}
exp = []string{"~*vars", "*processedProfileIDs[cgrates.org:ATTR]"}
if rcv := SplitPath("~*vars.*processedProfileIDs[cgrates.org:ATTR]",
NestingSep[0], -1); !reflect.DeepEqual(rcv, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv)
}
exp = []string{"*notexists", "~*vars.*processedProfileIDs[<~*vars.apTenantID>]", ""}
if rcv := SplitPath("*notexists:~*vars.*processedProfileIDs[<~*vars.apTenantID>]:", InInFieldSep[0], -1); !reflect.DeepEqual(rcv, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv)
}
exp = []string{"~*vars", "*processedProfileIDs[<~*vars.apTenantID>]"}
if rcv := SplitPath("~*vars.*processedProfileIDs[<~*vars.apTenantID>]",
NestingSep[0], -1); !reflect.DeepEqual(rcv, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv)
}
}
func TestCoreUtilsFibSeqNrOverflow(t *testing.T) {
fib := Fib()
for i := 0; i < 92; i++ { // the 93rd fibonacci number in the sequence would normally overflow
fib()
}
exp := fib()
for i := 0; i < 100; i++ {
if rcv := fib(); rcv != exp {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv)
}
}
}
func TestCoreUtilsFibDurationSeqNrOverflow(t *testing.T) {
fib := FibDuration(time.Second, 0)
for i := 0; i < 49; i++ { // the 50th fibonacci number in the sequence would normally overflow when multiplied with time.Second
fib()
}
for i := 0; i < 100; i++ {
if rcv := fib(); rcv != AbsoluteMaxDuration {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", AbsoluteMaxDuration, rcv)
}
}
fib = FibDuration(time.Second, 6)
if rcv := fib(); rcv != 6 {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", AbsoluteMaxDuration, rcv)
}
}