Files
cgrates/config/generalcfg_test.go
2025-10-29 19:42:24 +01:00

249 lines
8.1 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 Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>
*/
package config
import (
"reflect"
"testing"
"time"
"github.com/cgrates/cgrates/utils"
)
func TestGeneralCfgloadFromJsonCfg(t *testing.T) {
var gencfg, expected GeneralCfg
if err := gencfg.loadFromJsonCfg(nil); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(gencfg, expected) {
t.Errorf("Expected: %+v ,received: %+v", expected, gencfg)
}
if err := gencfg.loadFromJsonCfg(new(GeneralJsonCfg)); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(gencfg, expected) {
t.Errorf("Expected: %+v ,received: %+v", expected, gencfg)
}
cfgJSONStr := `{
"general": {
"node_id": "", // identifier of this instance in the cluster, if empty it will be autogenerated
"logger":"*syslog", // controls the destination of logs <*syslog|*stdout>
"log_level": 6, // control the level of messages logged (0-emerg to 7-debug)
"http_skip_tls_verify": false, // if enabled Http Client will accept any TLS certificate
"rounding_decimals": 5, // system level precision for floats
"dbdata_encoding": "msgpack", // encoding used to store object data in strings: <msgpack|json>
"tpexport_dir": "/var/spool/cgrates/tpe", // path towards export folder for offline Tariff Plans
"poster_attempts": 3, // number of attempts before considering post request failed (eg: *http_post, CDR replication)
"failed_posts_dir": "/var/spool/cgrates/failed_posts", // directory path where we store failed requests
"default_request_type": "*rated", // default request type to consider when missing from requests: <""|*prepaid|*postpaid|*pseudoprepaid|*rated>
"default_category": "call", // default category to consider when missing from requests
"default_tenant": "cgrates.org", // default tenant to consider when missing from requests
"default_timezone": "Local", // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB>
"connect_attempts": 3, // initial server connect attempts
"reconnects": -1, // number of retries in case of connection lost
"connect_timeout": "1s", // consider connection unsuccessful on timeout, 0 to disable the feature
"reply_timeout": "2s", // consider connection down for replies taking longer than this value
"response_cache_ttl": "0s", // the life span of a cached response
"locking_timeout": "0", // timeout internal locks to avoid deadlocks
"digest_separator": ",",
"digest_equal": ":",
"concurrent_requests": 0,
"concurrent_strategy": "",
}
}`
expected = GeneralCfg{
NodeID: "",
Logger: "*syslog",
LogLevel: 6,
HttpSkipTlsVerify: false,
RoundingDecimals: 5,
DBDataEncoding: "msgpack",
TpExportPath: "/var/spool/cgrates/tpe",
PosterAttempts: 3,
FailedPostsDir: "/var/spool/cgrates/failed_posts",
DefaultReqType: "*rated",
DefaultCategory: "call",
DefaultTenant: "cgrates.org",
DefaultTimezone: "Local",
ConnectAttempts: 3,
Reconnects: -1,
ConnectTimeout: time.Duration(1 * time.Second),
ReplyTimeout: time.Duration(2 * time.Second),
DigestSeparator: ",",
DigestEqual: ":",
ConcurrentRequests: 0,
ConcurrentStrategy: utils.EmptyString,
}
if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil {
t.Error(err)
} else if jsnGenCfg, err := jsnCfg.GeneralJsonCfg(); err != nil {
t.Error(err)
} else if err = gencfg.loadFromJsonCfg(jsnGenCfg); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expected, gencfg) {
t.Errorf("Expected: %+v , received: %+v", expected, gencfg)
}
}
func TestGeneralCfgAsMapInterface(t *testing.T) {
var gencfg GeneralCfg
cfgJSONStr := `{
"general": {
"node_id": "",
"logger":"*syslog",
"log_level": 6,
"http_skip_tls_verify": false,
"rounding_decimals": 5,
"dbdata_encoding": "*msgpack",
"tpexport_dir": "/var/spool/cgrates/tpe",
"poster_attempts": 3,
"failed_posts_dir": "/var/spool/cgrates/failed_posts",
"failed_posts_ttl": "5s",
"default_request_type": "*rated",
"default_category": "call",
"default_tenant": "cgrates.org",
"default_timezone": "Local",
"default_caching":"*reload",
"connect_attempts": 5,
"reconnects": -1,
"connect_timeout": "1s",
"reply_timeout": "2s",
"locking_timeout": "0",
"digest_separator": ",",
"digest_equal": ":",
"rsr_separator": ";",
"max_parallel_conns": 100,
"concurrent_requests": 0,
"concurrent_strategy": "",
},
}`
eMap := map[string]any{
"node_id": "",
"logger": "*syslog",
"log_level": 6,
"http_skip_tls_verify": false,
"rounding_decimals": 5,
"dbdata_encoding": "*msgpack",
"tpexport_dir": "/var/spool/cgrates/tpe",
"poster_attempts": 3,
"failed_posts_dir": "/var/spool/cgrates/failed_posts",
"failed_posts_ttl": "5s",
"default_request_type": "*rated",
"default_category": "call",
"default_tenant": "cgrates.org",
"default_timezone": "Local",
"default_caching": "*reload",
"connect_attempts": 5,
"reconnects": -1,
"connect_timeout": "1s",
"reply_timeout": "2s",
"locking_timeout": "0",
"digest_separator": ",",
"digest_equal": ":",
"rsr_separator": ";",
"max_parallel_conns": 100,
"concurrent_requests": 0,
"concurrent_strategy": "",
}
if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil {
t.Error(err)
} else if jsnGenCfg, err := jsnCfg.GeneralJsonCfg(); err != nil {
t.Error(err)
} else if err = gencfg.loadFromJsonCfg(jsnGenCfg); err != nil {
t.Error(err)
} else if rcv := gencfg.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) {
t.Errorf("\nExpected: %+v\nReceived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv))
}
}
func TestGeneralCfgloadFromJsonCfg2(t *testing.T) {
id := "id"
g := GeneralCfg{}
js := GeneralJsonCfg{
Node_id: &id,
}
err := g.loadFromJsonCfg(&js)
if err != nil {
t.Error(err)
}
if g.NodeID != id {
t.Errorf("received %s", g.NodeID)
}
}
func TestGeneralCfgloadFromJsonCfgErrors(t *testing.T) {
strErr := "test"
g := GeneralCfg{}
tests := []struct {
name string
arg *GeneralJsonCfg
err string
}{
{
name: "Connect timeout error check",
arg: &GeneralJsonCfg{
Connect_timeout: &strErr,
},
err: `time: invalid duration "test"`,
},
{
name: "Reply timeout error check",
arg: &GeneralJsonCfg{
Reply_timeout: &strErr,
},
err: `time: invalid duration "test"`,
},
{
name: "Failed posts ttl error check",
arg: &GeneralJsonCfg{
Failed_posts_ttl: &strErr,
},
err: `time: invalid duration "test"`,
},
{
name: "Locking timeout error check",
arg: &GeneralJsonCfg{
Locking_timeout: &strErr,
},
err: `time: invalid duration "test"`,
},
}
for _, tt := range tests {
err := g.loadFromJsonCfg(tt.arg)
if err.Error() != tt.err {
t.Errorf("received %s, expecting %s", err, tt.err)
}
}
}
func TestGeneralCfgAsMapInterface2(t *testing.T) {
g := GeneralCfg{
LockingTimeout: 1 * time.Millisecond,
}
rcv := g.AsMapInterface()
if rcv["locking_timeout"] != "1ms" {
t.Errorf("received %s, expected %s", rcv["locking_timeout"], "1ms")
}
}