Add coverage tests on sessions && ips

This commit is contained in:
armirveliaj
2025-09-02 10:43:39 -04:00
committed by Dan Christian Bogos
parent 3ee6355cd2
commit 0aae6f5d26
4 changed files with 356 additions and 0 deletions

View File

@@ -443,3 +443,29 @@ func TestGetMaxUsageFromRuns(t *testing.T) {
})
}
}
func TestApplyFlags(t *testing.T) {
flags := utils.FlagsWithParams{
utils.MetaAccounts: utils.FlagParams{},
utils.MetaResources: utils.FlagParams{"false": {""}},
utils.MetaIPs: utils.FlagParams{"true": {""}},
}
opts := make(map[string]any)
ApplyFlags(utils.MetaAuthorize, flags, opts)
if v, ok := opts[utils.MetaAccounts]; !ok || v != true {
t.Errorf("expected %s=true, got %v", utils.MetaAccounts, opts[utils.MetaAccounts])
}
if v, ok := opts[utils.MetaResources]; !ok || v != false {
t.Errorf("expected %s=false, got %v", utils.MetaResources, opts[utils.MetaResources])
}
if v, ok := opts[utils.MetaIPs]; !ok || v != true {
t.Errorf("expected %s=true, got %v", utils.MetaIPs, opts[utils.MetaIPs])
}
opts2 := make(map[string]any)
ApplyFlags("unknownType", flags, opts2)
if len(opts2) != 0 {
t.Errorf("expected no opts set for unknown reqType, got %+v", opts2)
}
}

View File

@@ -750,3 +750,143 @@ func TestNewSession(t *testing.T) {
t.Errorf("Expected second SRuns to have runID 'run2', got %s", session.SRuns[1].CGREvent.APIOpts["runID"])
}
}
func TestSessionAsExternalSession(t *testing.T) {
tTime1 := time.Now()
tTime2 := time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)
session := &Session{
ID: "sess1",
SRuns: []*SRun{
{
ID: "run1",
CGREvent: &utils.CGREvent{Tenant: "cgrates1.org", ID: "event1"},
NextAutoDebit: &tTime1,
},
{
ID: "run2",
CGREvent: &utils.CGREvent{Tenant: "cgrates2.org", ID: "event2"},
NextAutoDebit: &tTime2,
},
{
ID: "run3",
CGREvent: &utils.CGREvent{Tenant: "cgrates3.org", ID: "event3"},
},
},
}
tests := []struct {
name string
sRunIdx int
nodeID string
expectedRunID string
expectedTenant string
expectedDebit *time.Time
}{
{
name: "First run with debit",
sRunIdx: 0,
nodeID: "nodeA",
expectedRunID: "run1",
expectedTenant: "cgrates1.org",
expectedDebit: &tTime1,
},
{
name: "Second run with debit",
sRunIdx: 1,
nodeID: "nodeB",
expectedRunID: "run2",
expectedTenant: "cgrates2.org",
expectedDebit: &tTime2,
},
{
name: "Third run without debit",
sRunIdx: 2,
nodeID: "nodeC",
expectedRunID: "run3",
expectedTenant: "cgrates3.org",
expectedDebit: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
aS := session.AsExternalSession(tt.sRunIdx, tt.nodeID)
if aS.ID != session.ID {
t.Errorf("Expected ID %s, got %s", session.ID, aS.ID)
}
if aS.RunID != tt.expectedRunID {
t.Errorf("Expected RunID %s, got %s", tt.expectedRunID, aS.RunID)
}
if aS.CGREvent.Tenant != tt.expectedTenant {
t.Errorf("Expected Tenant %s, got %s", tt.expectedTenant, aS.CGREvent.Tenant)
}
if aS.NodeID != tt.nodeID {
t.Errorf("Expected NodeID %s, got %s", tt.nodeID, aS.NodeID)
}
if tt.expectedDebit != nil {
if aS.NextAutoDebit != *tt.expectedDebit {
t.Errorf("Expected NextAutoDebit %v, got %v", *tt.expectedDebit, aS.NextAutoDebit)
}
} else if aS.NextAutoDebit != (time.Time{}) {
t.Errorf("Expected NextAutoDebit to be zero, got %v", aS.NextAutoDebit)
}
})
}
}
func TestSessionUpdateSRuns(t *testing.T) {
sr1 := &SRun{
ID: "run1",
CGREvent: &utils.CGREvent{
Event: map[string]any{
"Destination": "1001",
"Subject": "1002",
},
},
}
sr2 := &SRun{
ID: "run2",
CGREvent: &utils.CGREvent{
Event: map[string]any{
"Destination": "1001",
"Subject": "2001",
},
},
}
session := &Session{
ID: "sess1",
SRuns: []*SRun{sr1, sr2},
}
updEv := engine.MapEvent{
"Destination": "3001",
"Subject": "4001",
}
alterableFields := utils.StringSet{"Destination": {}}
session.updateSRuns(updEv, alterableFields)
for i, sr := range session.SRuns {
if sr.CGREvent.Event["Destination"] != "3001" {
t.Errorf("SRun[%d]: Expected Destination '3001', got %v", i, sr.CGREvent.Event["Destination"])
}
expectedSubject := "1002"
if i == 1 {
expectedSubject = "2001"
}
if sr.CGREvent.Event["Subject"] != expectedSubject {
t.Errorf("SRun[%d]: Expected Subject '%s', got %v", i, expectedSubject, sr.CGREvent.Event["Subject"])
}
}
session2 := &Session{
SRuns: []*SRun{sr1},
}
session2.updateSRuns(updEv, utils.StringSet{})
if session2.SRuns[0].CGREvent.Event["Destination"] != "3001" {
t.Errorf("Expected Destination to remain '3001' when alterableFields is empty, got %v", session2.SRuns[0].CGREvent.Event["Destination"])
}
}

View File

@@ -2227,3 +2227,99 @@ func TestIPAllocationsComputeUnexported(t *testing.T) {
})
}
}
func TestIPAllocationsClearAllocations(t *testing.T) {
addr1 := netip.MustParseAddr("192.168.1.10")
addr2 := netip.MustParseAddr("192.168.1.11")
ip1 := netip.MustParseAddr("192.168.1.10")
ip2 := netip.MustParseAddr("192.168.1.11")
alloc := &IPAllocations{
Tenant: "cgrates.org",
ID: "profile1",
Allocations: map[string]*PoolAllocation{
"a1": {
PoolID: "pool1",
Address: ip1,
Time: time.Now().Add(-2 * time.Minute),
},
"a2": {
PoolID: "pool1",
Address: ip2,
Time: time.Now().Add(-1 * time.Minute),
},
},
TTLIndex: []string{"a1", "a2"},
prfl: &IPProfile{
Tenant: "cgrates.org",
ID: "profile1",
TTL: time.Minute,
Stored: true,
Pools: []*IPPool{
{
ID: "pool1",
Type: "*ipv4",
Range: "192.168.1.0/24",
Strategy: "*ascending",
},
},
},
poolRanges: map[string]netip.Prefix{
"pool1": netip.MustParsePrefix("192.168.1.0/24"),
},
poolAllocs: map[string]map[netip.Addr]string{
"pool1": {
ip1: "a1",
ip2: "a2",
},
},
}
alloc.Allocations["a1"] = &PoolAllocation{PoolID: "p1", Address: addr1, Time: time.Now()}
alloc.Allocations["a2"] = &PoolAllocation{PoolID: "p1", Address: addr2, Time: time.Now()}
alloc.TTLIndex = []string{"a1", "a2"}
alloc.poolAllocs["p1"] = map[netip.Addr]string{
addr1: "a1",
addr2: "a2",
}
err := alloc.ClearAllocations([]string{"doesNotExist"})
if err == nil {
t.Errorf("expected error for missing allocation ID")
}
if len(alloc.Allocations) != 2 {
t.Errorf("expected allocations unchanged, got %d", len(alloc.Allocations))
}
err = alloc.ClearAllocations([]string{"a1"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, ok := alloc.Allocations["a1"]; ok {
t.Errorf("expected a1 to be cleared")
}
if _, ok := alloc.Allocations["a2"]; !ok {
t.Errorf("expected a2 to remain")
}
if _, ok := alloc.poolAllocs["p1"][addr1]; ok {
t.Errorf("expected addr1 to be removed from poolAllocs")
}
if len(alloc.TTLIndex) != 1 || alloc.TTLIndex[0] != "a2" {
t.Errorf("expected TTLIndex to contain only a2, got %v", alloc.TTLIndex)
}
err = alloc.ClearAllocations(nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(alloc.Allocations) != 0 {
t.Errorf("expected all allocations cleared, got %d", len(alloc.Allocations))
}
if len(alloc.poolAllocs["p1"]) != 0 {
t.Errorf("expected all poolAllocs cleared, got %d", len(alloc.poolAllocs["p1"]))
}
if len(alloc.TTLIndex) != 0 {
t.Errorf("expected TTLIndex cleared, got %v", alloc.TTLIndex)
}
}

View File

@@ -20,6 +20,7 @@ package utils
import (
"reflect"
"strings"
"testing"
"time"
@@ -2492,3 +2493,96 @@ func TestNewRateProfileFromMapDataDBMap(t *testing.T) {
t.Errorf("Expected error <%v>, received <%v>", expErr, err)
}
}
func TestRateSIncrementFieldAsInterface(t *testing.T) {
incStart := &Decimal{Big: decimal.New(123, -2)}
usage := &Decimal{Big: decimal.New(456, -2)}
rI := &RateSIncrement{
IncrementStart: incStart,
RateIntervalIndex: 5,
RateID: "rateID1",
CompressFactor: 2,
Usage: usage,
}
tests := []struct {
name string
fldPath []string
expectedVal any
expectErr bool
expectedErr string
}{
{
name: "IncrementStart returns Decimal",
fldPath: []string{IncrementStart},
expectedVal: incStart,
expectErr: false,
},
{
name: "RateIntervalIndex returns int",
fldPath: []string{RateIntervalIndex},
expectedVal: 5,
expectErr: false,
},
{
name: "RateID returns string",
fldPath: []string{RateID},
expectedVal: "rateID1",
expectErr: false,
},
{
name: "CompressFactor returns int64",
fldPath: []string{CompressFactor},
expectedVal: int64(2),
expectErr: false,
},
{
name: "Usage returns Decimal",
fldPath: []string{Usage},
expectedVal: usage,
expectErr: false,
},
{
name: "UnknownField returns error",
fldPath: []string{"UnknownField"},
expectedVal: nil,
expectErr: true,
expectedErr: "unsupported field prefix",
},
{
name: "Empty path returns error",
fldPath: []string{},
expectedVal: nil,
expectErr: true,
expectedErr: "NOT_FOUND",
},
{
name: "Too many path parts returns error",
fldPath: []string{"NFound", "NFound"},
expectedVal: nil,
expectErr: true,
expectedErr: "NOT_FOUND",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
val, err := rI.FieldAsInterface(tt.fldPath)
if tt.expectErr {
if err == nil {
t.Errorf("Expected error for field path %v, got nil", tt.fldPath)
} else if tt.expectedErr != "" && !strings.Contains(strings.ToUpper(err.Error()), strings.ToUpper(tt.expectedErr)) {
t.Errorf("Expected error containing %q, got %v", tt.expectedErr, err)
}
} else {
if err != nil {
t.Errorf("Unexpected error for field path %v: %v", tt.fldPath, err)
} else if !reflect.DeepEqual(val, tt.expectedVal) {
t.Errorf("For field path %v, expected %v, got %v", tt.fldPath, tt.expectedVal, val)
}
}
})
}
}