Add coverage tests on ips

This commit is contained in:
armirveliaj
2025-07-23 10:51:43 -04:00
committed by Dan Christian Bogos
parent 50a06f0c44
commit b4de0dc84c

View File

@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"reflect"
"testing"
"time"
@@ -235,3 +236,249 @@ func TestIPUsageIsActive(t *testing.T) {
t.Errorf("Expected active usage for zero expiry time, got inactive")
}
}
func TestIPTotalUsage(t *testing.T) {
ip := &IP{
Usages: map[string]*IPUsage{
"u1": {Units: 1.5},
"u2": {Units: 2.0},
"u3": {Units: 0.5},
},
}
expected := 4.0
got := ip.TotalUsage()
if got != expected {
t.Errorf("TotalUsage() = %v, want %v", got, expected)
}
gotCached := ip.TotalUsage()
if gotCached != expected {
t.Errorf("TotalUsage() after cache = %v, want %v", gotCached, expected)
}
}
func TestIPUsageClone(t *testing.T) {
original := &IPUsage{
Tenant: "cgrates.org",
ID: "ID1001",
ExpiryTime: time.Now().Add(24 * time.Hour),
}
cloned := original.Clone()
if cloned == nil {
t.Fatal("expected clone not to be nil")
}
if cloned == original {
t.Error("expected clone to be a different instance")
}
if *cloned != *original {
t.Errorf("expected clone to have same content, got %+v, want %+v", cloned, original)
}
var nilUsage *IPUsage
nilClone := nilUsage.Clone()
if nilClone != nil {
t.Error("expected nil clone for nil input")
}
}
func TestIPClone(t *testing.T) {
ttl := 5 * time.Minute
tUsage := 123.45
dirty := true
expTime := time.Now().Add(time.Hour)
original := &IP{
Tenant: "cgrates.org",
ID: "ip01",
TTLIdx: []string{"idx1", "idx2"},
cfg: &IPProfile{
Tenant: "cgrates.org",
ID: "profile1",
FilterIDs: []string{"f1", "f2"},
TTL: time.Minute * 10,
Type: "dynamic",
},
Usages: map[string]*IPUsage{
"u1": {
Tenant: "cgrates.org",
ID: "u1",
ExpiryTime: expTime,
Units: 50.0,
},
},
ttl: &ttl,
tUsage: &tUsage,
dirty: &dirty,
}
cloned := original.Clone()
t.Run("nil IP returns nil", func(t *testing.T) {
var ip *IP = nil
cloned := ip.Clone()
if cloned != nil {
t.Errorf("expected nil, got %+v", cloned)
}
})
if !reflect.DeepEqual(original, cloned) {
t.Errorf("Expected clone to be deeply equal to original, got difference:\noriginal: %+v\nclone: %+v", original, cloned)
}
if cloned == original {
t.Error("Clone should return a different pointer than the original")
}
if cloned.cfg == original.cfg {
t.Error("cfg field was not deeply cloned")
}
if cloned.Usages["u1"] == original.Usages["u1"] {
t.Error("Usages map content was not deeply cloned")
}
if cloned.ttl == original.ttl {
t.Error("ttl pointer was not deeply cloned")
}
if cloned.tUsage == original.tUsage {
t.Error("tUsage pointer was not deeply cloned")
}
if cloned.dirty == original.dirty {
t.Error("dirty pointer was not deeply cloned")
}
}
func TestIpLockKey(t *testing.T) {
tnt := "cgrates.org"
id := "192.168.0.1"
expected := utils.ConcatenatedKey(utils.CacheIPs, tnt, id)
got := ipLockKey(tnt, id)
if got != expected {
t.Errorf("Expected %s, got %s", expected, got)
}
}
func TestIPlock(t *testing.T) {
ip := &IP{Tenant: "cgrates.org", ID: "1001"}
ip.lock("customLockID")
if ip.lkID != "customLockID" {
t.Errorf("Expected lkID to be 'customLockID', got %s", ip.lkID)
}
ip2 := &IP{Tenant: "cgrates.org2", ID: "1002"}
ip2.lock(utils.EmptyString)
if ip2.lkID == utils.EmptyString {
t.Error("Expected lkID to be set by Guardian.GuardIDs, got empty string")
}
}
func TestIPUunlock(t *testing.T) {
ip := &IP{lkID: "LockID"}
ip.unlock()
if ip.lkID != utils.EmptyString {
t.Errorf("Expected lkID to be cleared, got %s", ip.lkID)
}
ip.unlock()
}
func TestIPRemoveExpiredUnits(t *testing.T) {
now := time.Now()
expiredID := "expired"
activeID := "active"
ip := &IP{
ID: "ip-test",
Usages: map[string]*IPUsage{},
TTLIdx: []string{expiredID, activeID},
tUsage: utils.Float64Pointer(30.0),
}
ip.Usages[expiredID] = &IPUsage{
ID: expiredID,
ExpiryTime: now.Add(-10 * time.Minute),
Units: 10.0,
}
ip.Usages[activeID] = &IPUsage{
ID: activeID,
ExpiryTime: now.Add(10 * time.Minute),
Units: 20.0,
}
ip.removeExpiredUnits()
if _, ok := ip.Usages[expiredID]; ok {
t.Errorf("Expected expired usage to be removed")
}
if _, ok := ip.Usages[activeID]; !ok {
t.Errorf("Expected active usage to be retained")
}
if ip.tUsage != nil {
t.Errorf("Expected tUsage to be set to nil after recalculation")
}
if len(ip.TTLIdx) != 1 || ip.TTLIdx[0] != activeID {
t.Errorf("Expected TTLIdx to only contain activeID")
}
}
func TestIPRecordUsage(t *testing.T) {
t.Run("record new usage with ttl set", func(t *testing.T) {
ttl := 10 * time.Minute
ip := &IP{
Usages: make(map[string]*IPUsage),
TTLIdx: []string{},
ttl: &ttl,
tUsage: new(float64),
}
usage := &IPUsage{Tenant: "cgrates.org", ID: "usage1", Units: 5}
err := ip.recordUsage(usage)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got, want := len(ip.Usages), 1; got != want {
t.Fatalf("unexpected number of usages: got %d, want %d", got, want)
}
if _, ok := ip.Usages[usage.ID]; !ok {
t.Fatal("usage not recorded")
}
if len(ip.TTLIdx) != 1 || ip.TTLIdx[0] != usage.ID {
t.Fatal("TTLIdx not updated properly")
}
if ip.tUsage == nil || *ip.tUsage != usage.Units {
t.Fatalf("tUsage not updated properly, got %v", ip.tUsage)
}
})
t.Run("duplicate usage id", func(t *testing.T) {
ip := &IP{
Usages: map[string]*IPUsage{
"usage1": {Tenant: "cgrates.org", ID: "usage1", Units: 5},
},
}
usage := &IPUsage{Tenant: "cgrates.org", ID: "usage1", Units: 10}
err := ip.recordUsage(usage)
if err == nil {
t.Fatal("expected error on duplicate usage id, got nil")
}
})
t.Run("ttl zero disables expiry setting", func(t *testing.T) {
zeroTTL := time.Duration(0)
ip := &IP{
Usages: make(map[string]*IPUsage),
ttl: &zeroTTL,
}
usage := &IPUsage{Tenant: "cgrates.org", ID: "noexpiry", Units: 2}
err := ip.recordUsage(usage)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(ip.Usages) != 0 {
t.Fatal("usage should NOT be recorded when ttl is 0")
}
})
}