diff --git a/config/rankingscfg_test.go b/config/rankingscfg_test.go new file mode 100644 index 000000000..72e1848d9 --- /dev/null +++ b/config/rankingscfg_test.go @@ -0,0 +1,183 @@ +/* +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 +*/ + +package config + +import ( + "reflect" + "testing" + + "github.com/cgrates/cgrates/utils" +) + +func TestRankingSCfgLoadFromJSONCfg(t *testing.T) { + tests := []struct { + name string + jsnCfg *RankingsJsonCfg + expectedCfg RankingSCfg + expectErr bool + }{ + { + name: "nil input", + jsnCfg: nil, + expectedCfg: RankingSCfg{}, + expectErr: false, + }, + + { + name: "enabled true, no stats conns", + jsnCfg: &RankingsJsonCfg{ + Enabled: utils.BoolPointer(true), + Stats_conns: nil, + }, + expectedCfg: RankingSCfg{ + Enabled: true, + }, + expectErr: false, + }, + + { + name: "enabled false with stats conns", + jsnCfg: &RankingsJsonCfg{ + Enabled: utils.BoolPointer(false), + Stats_conns: &[]string{"conn1", utils.MetaInternal}, + }, + expectedCfg: RankingSCfg{ + Enabled: false, + StatSConns: []string{"conn1", utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)}, + }, + expectErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var sgsCfg RankingSCfg + err := sgsCfg.loadFromJSONCfg(tt.jsnCfg) + + if (err != nil) != tt.expectErr { + t.Errorf("loadFromJSONCfg() error = %v, expectErr %v", err, tt.expectErr) + return + } + + if !reflect.DeepEqual(sgsCfg, tt.expectedCfg) { + t.Errorf("loadFromJSONCfg() = %v, want %v", sgsCfg, tt.expectedCfg) + } + }) + } +} + +func TestRankingSCfgClone(t *testing.T) { + tests := []struct { + name string + originalCfg RankingSCfg + expectedClone RankingSCfg + }{ + { + name: "enabled true, no stat conns", + originalCfg: RankingSCfg{ + Enabled: true, + StatSConns: nil, + }, + expectedClone: RankingSCfg{ + Enabled: true, + StatSConns: nil, + }, + }, + + { + name: "enabled false, stat conns present", + originalCfg: RankingSCfg{ + Enabled: false, + StatSConns: []string{"conn1", "conn2"}, + }, + expectedClone: RankingSCfg{ + Enabled: false, + StatSConns: []string{"conn1", "conn2"}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + clone := tt.originalCfg.Clone() + + if !reflect.DeepEqual(clone, &tt.expectedClone) { + t.Errorf("Clone() = %v, want %v", clone, &tt.expectedClone) + } + + if clone.StatSConns != nil && tt.originalCfg.StatSConns != nil && &clone.StatSConns[0] == &tt.originalCfg.StatSConns[0] { + t.Errorf("StatSConns points to the same slice, expected a deep copy") + } + }) + } +} + +func TestRankingSCfgAsMapInterface(t *testing.T) { + + tests := []struct { + name string + rankingSCfg RankingSCfg + expectedMap map[string]any + }{ + { + name: "enabled true, no stat conns", + rankingSCfg: RankingSCfg{ + Enabled: true, + StatSConns: nil, + }, + expectedMap: map[string]any{ + utils.EnabledCfg: true, + }, + }, + + { + name: "enabled false, stat conns with MetaInternal", + rankingSCfg: RankingSCfg{ + Enabled: false, + StatSConns: []string{"conn1", utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)}, + }, + expectedMap: map[string]any{ + utils.EnabledCfg: false, + utils.StatSConnsCfg: []string{"conn1", utils.MetaInternal}, + }, + }, + + { + name: "stat conns without MetaInternal", + rankingSCfg: RankingSCfg{ + Enabled: false, + StatSConns: []string{"conn1", "conn2"}, + }, + expectedMap: map[string]any{ + utils.EnabledCfg: false, + utils.StatSConnsCfg: []string{"conn1", "conn2"}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.rankingSCfg.AsMapInterface() + + if !reflect.DeepEqual(result, tt.expectedMap) { + t.Errorf("AsMapInterface() = %v, want %v", result, tt.expectedMap) + } + }) + } +} diff --git a/engine/storage_csv_test.go b/engine/storage_csv_test.go index 5ab6fcffd..cd7512872 100644 --- a/engine/storage_csv_test.go +++ b/engine/storage_csv_test.go @@ -394,3 +394,19 @@ func TestGetTPTrends(t *testing.T) { } } } + +func TestNewURLCSVStorage(t *testing.T) { + sep := ',' + dataPath := "http://cgrates.com/destinations.csv;http://cgrates.com/timings.csv;http://cgrates.com/invalidpath" + + csvStorage := NewURLCSVStorage(sep, dataPath) + + if csvStorage == nil { + t.Fatal("Expected csvStorage to be initialized, but got nil") + } + + if csvStorage.generator == nil { + t.Fatal("Expected csvStorage.generator to be initialized, but got nil") + } + +} diff --git a/engine/storage_mongo_datadb_test.go b/engine/storage_mongo_datadb_test.go new file mode 100644 index 000000000..2bc2c0038 --- /dev/null +++ b/engine/storage_mongo_datadb_test.go @@ -0,0 +1,129 @@ +/* +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 +*/ + +package engine + +import ( + "errors" + "testing" + "time" + + "github.com/cgrates/cgrates/utils" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" +) + +func TestMongoErrIsNotFound(t *testing.T) { + + t.Run("mongo.CommandError with Code 26", func(t *testing.T) { + err := &mongo.CommandError{Code: 26, Message: "some message"} + if !isNotFound(err) { + t.Errorf("expected true, got false for mongo.CommandError with Code 26") + } + }) + + t.Run("mongo.CommandError with 'ns not found' message", func(t *testing.T) { + err := &mongo.CommandError{Code: 100, Message: "ns not found"} + if !isNotFound(err) { + t.Errorf("expected true, got false for mongo.CommandError with 'ns not found' message") + } + }) + + t.Run("Non-mongo.CommandError but 'ns not found' in message", func(t *testing.T) { + err := errors.New("some random error: ns not found") + if !isNotFound(err) { + t.Errorf("expected true, got false for error with 'ns not found' in message") + } + }) + + t.Run("Unrelated error", func(t *testing.T) { + err := errors.New("some other error") + if isNotFound(err) { + t.Errorf("expected false, got true for unrelated error") + } + }) + +} + +func TestCleanEmptyFilters(t *testing.T) { + ms := &MongoStorage{} + + tests := []struct { + name string + input bson.M + expected bson.M + }{ + { + name: "Remove nil int64", + input: bson.M{ + "field1": (*int64)(nil), + "field2": int64(5), + }, + expected: bson.M{ + "field2": int64(5), + }, + }, + { + name: "Remove nil float64", + input: bson.M{ + "field1": (*float64)(nil), + "field2": float64(3.14), + }, + expected: bson.M{ + "field2": float64(3.14), + }, + }, + + { + name: "Remove nil time.Duration", + input: bson.M{ + "field1": (*time.Duration)(nil), + "field2": time.Duration(5), + }, + expected: bson.M{ + "field2": time.Duration(5), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ms.cleanEmptyFilters(tt.input) + if len(tt.input) != len(tt.expected) { + t.Errorf("Expected %d keys, got %d", len(tt.expected), len(tt.input)) + } + for k, v := range tt.expected { + if inputValue, exists := tt.input[k]; !exists || inputValue != v { + t.Errorf("Key %s: expected %v, got %v", k, v, inputValue) + } + } + }) + } +} + +func TestMongoStoreDBGetStorageType(t *testing.T) { + ms := &MongoStorage{} + + result := ms.GetStorageType() + + expected := utils.MetaMongo + + if result != expected { + t.Errorf("Expected %s, got %s", expected, result) + } +}