revised sortingStatIDs method for each rankingSorter

This commit is contained in:
gezimbll
2024-12-16 09:05:47 +01:00
committed by Dan Christian Bogos
parent cd3159d8ea
commit 36420e2b84
4 changed files with 203 additions and 2 deletions

1
engine/coverage.out Normal file
View File

@@ -0,0 +1 @@
mode: set

View File

@@ -205,10 +205,13 @@ func (rkDsrtr *rankingDescSorter) sortStatIDs() []string {
sort.Slice(rkDsrtr.statIDs, func(i, j int) bool {
for _, metricID := range rkDsrtr.sMetricIDs {
val1, hasMetric1 := rkDsrtr.Metrics[rkDsrtr.statIDs[i]][metricID]
val2, hasMetric2 := rkDsrtr.Metrics[rkDsrtr.statIDs[j]][metricID]
if !hasMetric1 && !hasMetric2 {
continue
}
if !hasMetric1 {
return false
}
val2, hasMetric2 := rkDsrtr.Metrics[rkDsrtr.statIDs[j]][metricID]
if !hasMetric2 {
return true
}
@@ -268,10 +271,13 @@ func (rkASrtr *rankingAscSorter) sortStatIDs() []string {
sort.Slice(rkASrtr.statIDs, func(i, j int) bool {
for _, metricID := range rkASrtr.sMetricIDs {
val1, hasMetric1 := rkASrtr.Metrics[rkASrtr.statIDs[i]][metricID]
val2, hasMetric2 := rkASrtr.Metrics[rkASrtr.statIDs[j]][metricID]
if !hasMetric1 && !hasMetric2 {
continue
}
if !hasMetric1 {
return false
}
val2, hasMetric2 := rkASrtr.Metrics[rkASrtr.statIDs[j]][metricID]
if !hasMetric2 {
return true
}

View File

@@ -239,3 +239,137 @@ func TestRankingSortStats(t *testing.T) {
})
}
}
func TestRankingMixedOrder(t *testing.T) {
statmetrics := map[string]map[string]float64{
"Stat1": {"*acc": 13},
"Stat6": {"*acc": 10, "*pdd": 700, "*tcc": 121},
"Stat2": {"*acc": 14},
"Stat5": {"*acc": 10, "*pdd": 700, "*tcc": 120},
"Stat3": {"*acc": 12.1, "*pdd": 900},
"Stat7": {"*acc": 10, "*pdd": 600, "*tcc": 123},
"Stat4": {"*acc": 12.1, "*pdd": 1000},
}
testCases := []struct {
name string
sortMetric []string
sorter string
statIDs []string
expErr error
}{
{
name: "TestSortStatsAsc",
sortMetric: []string{"*acc", "*pdd:false", "*tcc"},
sorter: "*asc",
statIDs: []string{"Stat5", "Stat6", "Stat7", "Stat4", "Stat3", "Stat1", "Stat2"},
},
{
name: "TestSortStatsDesc",
sortMetric: []string{"*tcc", "*pdd:false", "*acc"},
sorter: "*desc",
statIDs: []string{"Stat7", "Stat6", "Stat5", "Stat3", "Stat4", "Stat2", "Stat1"},
},
{
name: "TestSortStatsDesc",
sortMetric: []string{"*acc", "*tcc", "*pdd:false"},
sorter: "*desc",
statIDs: []string{"Stat2", "Stat1", "Stat3", "Stat4", "Stat7", "Stat6", "Stat5"},
},
{
name: "TestSortStatsAsc",
sortMetric: []string{"*tcc", "*pdd:false", "*acc"},
sorter: "*asc",
statIDs: []string{"Stat5", "Stat6", "Stat7", "Stat4", "Stat3", "Stat1", "Stat2"},
},
{
name: "TestSortStatsDesc",
sortMetric: []string{"*pdd:false", "*acc", "*tcc"},
sorter: "*desc",
statIDs: []string{"Stat7", "Stat6", "Stat5", "Stat3", "Stat4", "Stat2", "Stat1"},
},
{
name: "TestSortStatsAsc",
sortMetric: []string{"*tcc", "*acc", "*pdd:false"},
sorter: "*asc",
statIDs: []string{"Stat5", "Stat6", "Stat7", "Stat4", "Stat3", "Stat1", "Stat2"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
rs, err := newRankingSorter(tc.sorter, tc.sortMetric, statmetrics)
if tc.expErr != nil {
if err == nil {
t.Error("Expected error, got nil")
}
if tc.expErr.Error() != err.Error() {
t.Errorf("Expected error: %v, got: %v", tc.expErr, err)
}
return
}
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if resStatIDs := rs.sortStatIDs(); !reflect.DeepEqual(resStatIDs, tc.statIDs) {
t.Errorf("Expecting: %v, received %v", tc.statIDs, resStatIDs)
}
})
}
}
func TestRankingProfileFieldAsString(t *testing.T) {
tests := []struct {
name string
fldPath []string
err error
val any
}{
{utils.ID, []string{utils.ID}, nil, "RP1"},
{utils.Tenant, []string{utils.Tenant}, nil, "cgrates.org"},
{utils.Schedule, []string{utils.Schedule}, nil, "@every 2s"},
{utils.StatIDs, []string{utils.StatIDs + "[0]"}, nil, "Stat1"},
{utils.StatIDs, []string{utils.StatIDs + "[1]"}, nil, "Stat2"},
{utils.MetricIDs, []string{utils.MetricIDs + "[0]"}, nil, "*tcc"},
{utils.MetricIDs, []string{utils.MetricIDs + "[1]"}, nil, "*acc"},
{utils.Sorting, []string{utils.Sorting}, nil, "*asc"},
{utils.Stored, []string{utils.Stored}, nil, false},
{utils.SortingParameters, []string{utils.SortingParameters + "[0]"}, nil, "*acc"},
{utils.SortingParameters, []string{utils.SortingParameters + "[1]"}, nil, "*pdd:false"},
{utils.ThresholdIDs, []string{utils.ThresholdIDs + "[0]"}, nil, "Threshold1"},
{utils.ThresholdIDs, []string{utils.ThresholdIDs + "[1]"}, nil, "Threshold2"},
{"NonExistingField", []string{"Field1"}, utils.ErrNotFound, nil},
}
rp := &RankingProfile{
Tenant: "cgrates.org",
ID: "RP1",
Schedule: "@every 2s",
StatIDs: []string{"Stat1", "Stat2"},
MetricIDs: []string{"*tcc", "*acc", "*pdd"},
Sorting: "*asc",
SortingParameters: []string{"*acc", "*pdd:false"},
ThresholdIDs: []string{"Threshold1", "Threshold2"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
val, err := rp.FieldAsInterface(tc.fldPath)
if tc.err != nil {
if err == nil {
t.Error("expect to receive an error")
}
if tc.err != err {
t.Errorf("expected %v,received %v", tc.err, err)
}
return
}
if err != nil {
t.Errorf("unexpected error %v", err)
}
if val != tc.val {
t.Errorf("expected %v,received %v", tc.val, val)
}
})
}
}

View File

@@ -410,3 +410,63 @@ func TestNewTrendFromProfile(t *testing.T) {
t.Errorf("Expected tPrfl to point to the original profile, got a different value")
}
}
func TestTrendProfileFieldAsString(t *testing.T) {
tests := []struct {
name string
fldPath []string
err error
val any
}{
{utils.ID, []string{utils.ID}, nil, "Trend1"},
{utils.Tenant, []string{utils.Tenant}, nil, "cgrates.org"},
{utils.Schedule, []string{utils.Schedule}, nil, "@every 1m"},
{utils.StatID, []string{utils.StatID}, nil, "Stat1"},
{utils.Metrics, []string{utils.Metrics + "[0]"}, nil, "*acc"},
{utils.Metrics, []string{utils.Metrics + "[1]"}, nil, "*tcd"},
{utils.TTL, []string{utils.TTL}, nil, 10 * time.Minute},
{utils.QueueLength, []string{utils.QueueLength}, nil, 100},
{utils.MinItems, []string{utils.MinItems}, nil, 10},
{utils.CorrelationType, []string{utils.CorrelationType}, nil, "*average"},
{utils.Tolerance, []string{utils.Tolerance}, nil, 0.05},
{utils.Stored, []string{utils.Stored}, nil, true},
{utils.ThresholdIDs, []string{utils.ThresholdIDs + "[0]"}, nil, "Thresh1"},
{utils.ThresholdIDs, []string{utils.ThresholdIDs + "[1]"}, nil, "Thresh2"},
{"NonExistingField", []string{"Field1"}, utils.ErrNotFound, nil},
}
rp := &TrendProfile{
Tenant: "cgrates.org",
ID: "Trend1",
Schedule: "@every 1m",
StatID: "Stat1",
Metrics: []string{"*acc", "*tcd"},
TTL: 10 * time.Minute,
QueueLength: 100,
MinItems: 10,
CorrelationType: "*average",
Tolerance: 0.05,
Stored: true,
ThresholdIDs: []string{"Thresh1", "Thresh2"},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
val, err := rp.FieldAsInterface(tc.fldPath)
if tc.err != nil {
if err == nil {
t.Error("expect to receive an error")
}
if tc.err != err {
t.Errorf("expected %v,received %v", tc.err, err)
}
return
}
if err != nil {
t.Errorf("unexpected error %v", err)
}
if val != tc.val {
t.Errorf("expected %v,received %v", tc.val, val)
}
})
}
}