mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
438 lines
14 KiB
Go
438 lines
14 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 loaders
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/cgrates/cgrates/engine"
|
|
|
|
"github.com/cgrates/cgrates/config"
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
func TestDataUpdateFromCSVOneFile(t *testing.T) {
|
|
attrSFlds := []*config.FCTemplate{
|
|
{Tag: "TenantID",
|
|
Path: "Tenant",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.0", utils.InfieldSep),
|
|
Mandatory: true},
|
|
{Tag: "ProfileID",
|
|
Path: "ID",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.1", utils.InfieldSep),
|
|
Mandatory: true},
|
|
{Tag: "Contexts",
|
|
Path: "Contexts",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.2", utils.InfieldSep)},
|
|
{Tag: "FilterIDs",
|
|
Path: "FilterIDs",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.3", utils.InfieldSep)},
|
|
{Tag: "ActivationInterval",
|
|
Path: "ActivationInterval",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.4", utils.InfieldSep)},
|
|
{Tag: "Path",
|
|
Path: "Path",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.5", utils.InfieldSep)},
|
|
{Tag: "Initial",
|
|
Path: "Initial",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.6", utils.InfieldSep)},
|
|
{Tag: "Substitute",
|
|
Path: "Substitute",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.7", utils.InfieldSep)},
|
|
{Tag: "Append",
|
|
Path: "Append",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.8", utils.InfieldSep)},
|
|
{Tag: "Weight",
|
|
Path: "Weight",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*req.9", utils.InfieldSep)},
|
|
}
|
|
|
|
rows := [][]string{
|
|
{"cgrates.org", "ATTR_1", "*sessions;*cdrs", "*string:Account:1007", "2014-01-14T00:00:00Z", "Account", "*any", "1001", "false", "10"},
|
|
{"cgrates.org", "ATTR_1", "", "", "", "Subject", "*any", "1001", "true", ""},
|
|
}
|
|
lData := make(LoaderData)
|
|
if err := lData.UpdateFromCSV("Attributes.csv", rows[0], attrSFlds,
|
|
"cgrates.org", nil); err != nil {
|
|
t.Error(err)
|
|
}
|
|
eLData := LoaderData{"Tenant": "cgrates.org",
|
|
"ID": "ATTR_1",
|
|
"Contexts": "*sessions;*cdrs",
|
|
"FilterIDs": "*string:Account:1007",
|
|
"ActivationInterval": "2014-01-14T00:00:00Z",
|
|
"Path": "Account",
|
|
"Initial": "*any",
|
|
"Substitute": "1001",
|
|
"Append": "false",
|
|
"Weight": "10",
|
|
}
|
|
if !reflect.DeepEqual(eLData, lData) {
|
|
t.Errorf("expecting: %+v, received: %+v", eLData, lData)
|
|
}
|
|
lData = make(LoaderData)
|
|
if err := lData.UpdateFromCSV("Attributes.csv", rows[1], attrSFlds,
|
|
"cgrates.org", nil); err != nil {
|
|
t.Error(err)
|
|
}
|
|
eLData = LoaderData{"Tenant": "cgrates.org",
|
|
"ID": "ATTR_1",
|
|
"Contexts": "",
|
|
"FilterIDs": "",
|
|
"ActivationInterval": "",
|
|
"Path": "Subject",
|
|
"Initial": "*any",
|
|
"Substitute": "1001",
|
|
"Append": "true",
|
|
"Weight": "",
|
|
}
|
|
if !reflect.DeepEqual(eLData, lData) {
|
|
t.Errorf("expecting: %+v, received: %+v", eLData, lData)
|
|
}
|
|
}
|
|
|
|
func TestDataUpdateFromCSVOneFile2(t *testing.T) {
|
|
attrSFlds := []*config.FCTemplate{
|
|
{Tag: "TenantID",
|
|
Path: "Tenant",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.0", utils.InfieldSep),
|
|
Mandatory: true},
|
|
{Tag: "ProfileID",
|
|
Path: "ID",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.1", utils.InfieldSep),
|
|
Mandatory: true},
|
|
{Tag: "Contexts",
|
|
Path: "Contexts",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.2", utils.InfieldSep)},
|
|
{Tag: "FilterIDs",
|
|
Path: "FilterIDs",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.3", utils.InfieldSep)},
|
|
{Tag: "ActivationInterval",
|
|
Path: "ActivationInterval",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.4", utils.InfieldSep)},
|
|
{Tag: "Path",
|
|
Path: "Path",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.5", utils.InfieldSep)},
|
|
{Tag: "Initial",
|
|
Path: "Initial",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.6", utils.InfieldSep)},
|
|
{Tag: "Substitute",
|
|
Path: "Substitute",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.7", utils.InfieldSep)},
|
|
{Tag: "Append",
|
|
Path: "Append",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.8", utils.InfieldSep)},
|
|
{Tag: "Weight",
|
|
Path: "Weight",
|
|
Type: utils.MetaVariable,
|
|
Value: config.NewRSRParsersMustCompile("~*req.9", utils.InfieldSep)},
|
|
}
|
|
|
|
rows := [][]string{
|
|
{"cgrates.org", "ATTR_1", "*sessions;*cdrs", "*string:Account:1007", "2014-01-14T00:00:00Z", "Account", "*any", "1001", "false", "10"},
|
|
{"cgrates.org", "ATTR_1", "", "", "", "Subject", "*any", "1001", "true", ""},
|
|
}
|
|
lData := make(LoaderData)
|
|
if err := lData.UpdateFromCSV("Attributes.csv", rows[0], attrSFlds,
|
|
"cgrates.org", nil); err != nil {
|
|
t.Error(err)
|
|
}
|
|
eLData := LoaderData{"Tenant": "cgrates.org",
|
|
"ID": "ATTR_1",
|
|
"Contexts": "*sessions;*cdrs",
|
|
"FilterIDs": "*string:Account:1007",
|
|
"ActivationInterval": "2014-01-14T00:00:00Z",
|
|
"Path": "Account",
|
|
"Initial": "*any",
|
|
"Substitute": "1001",
|
|
"Append": "false",
|
|
"Weight": "10",
|
|
}
|
|
if !reflect.DeepEqual(eLData, lData) {
|
|
t.Errorf("expecting: %+v, received: %+v", eLData, lData)
|
|
}
|
|
lData = make(LoaderData)
|
|
if err := lData.UpdateFromCSV("Attributes.csv", rows[1], attrSFlds,
|
|
"cgrates.org", nil); err != nil {
|
|
t.Error(err)
|
|
}
|
|
eLData = LoaderData{"Tenant": "cgrates.org",
|
|
"ID": "ATTR_1",
|
|
"Contexts": "",
|
|
"FilterIDs": "",
|
|
"ActivationInterval": "",
|
|
"Path": "Subject",
|
|
"Initial": "*any",
|
|
"Substitute": "1001",
|
|
"Append": "true",
|
|
"Weight": "",
|
|
}
|
|
if !reflect.DeepEqual(eLData, lData) {
|
|
t.Errorf("expecting: %+v, received: %+v", eLData, lData)
|
|
}
|
|
}
|
|
|
|
func TestDataUpdateFromCSVMultiFiles(t *testing.T) {
|
|
attrSFlds := []*config.FCTemplate{
|
|
{Tag: "TenantID",
|
|
Path: "Tenant",
|
|
Type: utils.MetaString,
|
|
Value: config.NewRSRParsersMustCompile("cgrates.org", utils.InfieldSep),
|
|
Mandatory: true},
|
|
{Tag: "ProfileID",
|
|
Path: "ID",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*file(File2.csv).1", utils.InfieldSep),
|
|
Mandatory: true},
|
|
{Tag: "Contexts",
|
|
Path: "Contexts",
|
|
Type: utils.MetaString,
|
|
Value: config.NewRSRParsersMustCompile("*any", utils.InfieldSep)},
|
|
{Tag: "Path",
|
|
Path: "Path",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*file(File1.csv).5", utils.InfieldSep)},
|
|
{Tag: "Initial",
|
|
Path: "Initial",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*file(File1.csv).6", utils.InfieldSep)},
|
|
{Tag: "Substitute",
|
|
Path: "Substitute",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*file(File1.csv).7", utils.InfieldSep)},
|
|
{Tag: "Append",
|
|
Path: "Append",
|
|
Type: utils.MetaString,
|
|
Value: config.NewRSRParsersMustCompile("true", utils.InfieldSep)},
|
|
{Tag: "Weight",
|
|
Path: "Weight",
|
|
Type: utils.MetaString,
|
|
Value: config.NewRSRParsersMustCompile("10", utils.InfieldSep)},
|
|
}
|
|
|
|
loadRun1 := map[string][]string{
|
|
"File1.csv": {"ignored", "ignored", "ignored", "ignored", "ignored", "Subject", "*any", "1001", "ignored", "ignored"},
|
|
"File2.csv": {"ignored", "ATTR_1"},
|
|
}
|
|
lData := make(LoaderData)
|
|
for fName, record := range loadRun1 {
|
|
if err := lData.UpdateFromCSV(fName, record, attrSFlds,
|
|
"cgrates.org", nil); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
eLData := LoaderData{"Tenant": "cgrates.org",
|
|
"ID": "ATTR_1",
|
|
"Contexts": "*any",
|
|
"Path": "Subject",
|
|
"Initial": "*any",
|
|
"Substitute": "1001",
|
|
"Append": "true",
|
|
"Weight": "10",
|
|
}
|
|
if !reflect.DeepEqual(eLData, lData) {
|
|
t.Errorf("expecting: %+v, received: %+v", eLData, lData)
|
|
}
|
|
}
|
|
|
|
func TestGetRateIDsLoaderData(t *testing.T) {
|
|
ldrData := LoaderData{
|
|
"File1.csv": []string{"Subject", "*any", "1001"},
|
|
}
|
|
expected := "cannot find RateIDs in <map[File1.csv:[Subject *any 1001]]>"
|
|
if _, err := ldrData.GetRateIDs(); err == nil || err.Error() != expected {
|
|
t.Errorf("Expected %+v, received %+v", expected, err)
|
|
}
|
|
}
|
|
|
|
// func TestUpdateFromCsvParseValueError(t *testing.T) {
|
|
// ldrData := LoaderData{
|
|
// "File1.csv": []string{"Subject", "*any", "1001"},
|
|
// }
|
|
// tnt := config.NewRSRParsersMustCompile("asd{*duration_seconds}", utils.InfieldSep)
|
|
// expected := "time: invalid duration \"asd\""
|
|
// if err := ldrData.UpdateFromCSV("File1.csv", nil, nil, tnt, nil); err == nil || err.Error() != expected {
|
|
// t.Errorf("Expected %+v, received %+v", expected, err)
|
|
// }
|
|
// }
|
|
|
|
func TestUpdateFromCsvWithFiltersError(t *testing.T) {
|
|
attrSFlds := []*config.FCTemplate{
|
|
{Tag: "TenantID",
|
|
Path: "Tenant",
|
|
Type: utils.MetaString,
|
|
Value: config.NewRSRParsersMustCompile("cgrates.org", utils.InfieldSep),
|
|
Filters: []string{"*string:~*req.Account:10"},
|
|
Mandatory: true},
|
|
{Tag: "ProfileID",
|
|
Path: "ID",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*file(File2.csv).1", utils.InfieldSep),
|
|
Filters: []string{"*string:~*req.Account:10"},
|
|
Mandatory: true},
|
|
}
|
|
loadRunStr := map[string][]string{
|
|
"File1.csv": {"cgrates.org", "TEST_1"},
|
|
}
|
|
lData := make(LoaderData)
|
|
|
|
cfg := config.NewDefaultCGRConfig()
|
|
data := engine.NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items)
|
|
dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
|
|
filterS := engine.NewFilterS(cfg, nil, dm)
|
|
|
|
for fName, record := range loadRunStr {
|
|
expected := "Ignoring record: [\"cgrates.org\" \"TEST_1\"] with error : strconv.Atoi: parsing \"Account\": invalid syntax"
|
|
if err := lData.UpdateFromCSV(fName, record, attrSFlds,
|
|
"cgrates.org", filterS); err == nil || err.Error() != expected {
|
|
t.Errorf("Expected %+v, received %+v", expected, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUpdateFromCsvWithFiltersContinue(t *testing.T) {
|
|
attrSFlds := []*config.FCTemplate{
|
|
{Tag: "TenantID",
|
|
Path: "Tenant",
|
|
Type: utils.MetaString,
|
|
Value: config.NewRSRParsersMustCompile("cgrates.org", utils.InfieldSep),
|
|
Filters: []string{`*string:~*req.2:10`},
|
|
Mandatory: true},
|
|
{Tag: "ProfileID",
|
|
Path: "ID",
|
|
Type: utils.MetaComposed,
|
|
Value: config.NewRSRParsersMustCompile("~*file(File2.csv).1", utils.InfieldSep),
|
|
Filters: []string{`*string:~*req.2:10`},
|
|
Mandatory: true},
|
|
}
|
|
loadRunStr := map[string][]string{
|
|
"File1.csv": {"Subject", "*any", "1001"},
|
|
}
|
|
lData := make(LoaderData)
|
|
|
|
cfg := config.NewDefaultCGRConfig()
|
|
data := engine.NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items)
|
|
dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
|
|
filterS := engine.NewFilterS(cfg, nil, dm)
|
|
|
|
for fName, record := range loadRunStr {
|
|
if err := lData.UpdateFromCSV(fName, record, attrSFlds,
|
|
"cgrates.org", filterS); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadersFieldAsInterfaceError(t *testing.T) {
|
|
loadRun1 := map[string][]string{
|
|
"File1.csv": {"ignored", "ignored", "ignored", "ignored", "ignored", "Subject", "*any", "1001", "ignored", "ignored"},
|
|
}
|
|
csvProv := newCsvProvider(loadRun1["File1.csv"], "File1.csv")
|
|
|
|
csvString := csvProv.String()
|
|
expected := "{}"
|
|
if csvString != expected {
|
|
t.Errorf("Expected %+v, received %+v", expected, csvString)
|
|
}
|
|
|
|
expected = "invalid prefix for : [File2.csv]"
|
|
if _, err := csvProv.FieldAsInterface([]string{"File2.csv"}); err == nil || err.Error() != expected {
|
|
t.Errorf("Expected %+v, received %+v", expected, err)
|
|
}
|
|
|
|
expected = "filter rule <[*file() ]> needs to end in )"
|
|
if _, err := csvProv.FieldAsInterface([]string{"*file()", ""}); err == nil || err.Error() != expected {
|
|
t.Errorf("Expected %+v, received %+q", expected, err)
|
|
}
|
|
|
|
expected = "filter rule <[*file() File1.csv]> needs to end in )"
|
|
if _, err := csvProv.FieldAsInterface([]string{"*file()", "File1.csv"}); err == nil || err.Error() != expected {
|
|
t.Errorf("Expected %+v, received %+q", expected, err)
|
|
}
|
|
}
|
|
|
|
func TestLibLoaderGetRateIDs(t *testing.T) {
|
|
cases := []struct {
|
|
input LoaderData
|
|
expectedIDs []string
|
|
expectedErr error
|
|
}{
|
|
{
|
|
input: LoaderData{utils.RateIDs: "id1,id2,id3"},
|
|
expectedIDs: []string{"id1,id2,id3"},
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
input: LoaderData{utils.RateIDs: ""},
|
|
expectedIDs: []string{},
|
|
expectedErr: nil,
|
|
},
|
|
{
|
|
input: LoaderData{},
|
|
expectedIDs: nil,
|
|
expectedErr: fmt.Errorf("cannot find RateIDs in <map[]>"),
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
ids, err := c.input.GetRateIDs()
|
|
if c.expectedErr != nil {
|
|
if err == nil || err.Error() != c.expectedErr.Error() {
|
|
t.Errorf("Expected error: %v, got: %v", c.expectedErr, err)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
}
|
|
if !reflect.DeepEqual(ids, c.expectedIDs) {
|
|
t.Errorf("Expected IDs: %v, got: %v", c.expectedIDs, ids)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLibLoaderFieldAsStringErrorHandling(t *testing.T) {
|
|
cP := &csvProvider{}
|
|
_, err := cP.FieldAsString([]string{"invalid", "path"})
|
|
if err == nil {
|
|
t.Error("Expected an error, but got nil")
|
|
}
|
|
}
|