From 0ca0750b3e4179b8aa0b9cf887a0217c8a1b966d Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Tue, 15 Jun 2021 17:13:45 +0300 Subject: [PATCH] Add tests for resources in engine --- engine/datadbmock.go | 6 +- engine/z_resources_test.go | 698 +++++++++++++++++++++++++++++++++++-- 2 files changed, 680 insertions(+), 24 deletions(-) diff --git a/engine/datadbmock.go b/engine/datadbmock.go index 7f801d162..795c193b7 100644 --- a/engine/datadbmock.go +++ b/engine/datadbmock.go @@ -34,6 +34,7 @@ type DataDBMock struct { GetResourceProfileDrvF func(tnt, id string) (*ResourceProfile, error) SetResourceProfileDrvF func(rp *ResourceProfile) error RemoveResourceProfileDrvF func(tnt, id string) error + SetResourceDrvF func(r *Resource) error GetStatQueueProfileDrvF func(tenant, id string) (sq *StatQueueProfile, err error) SetStatQueueProfileDrvF func(sq *StatQueueProfile) (err error) RemStatQueueProfileDrvF func(tenant, id string) (err error) @@ -235,7 +236,10 @@ func (dbM *DataDBMock) GetResourceDrv(string, string) (*Resource, error) { return nil, utils.ErrNotImplemented } -func (dbM *DataDBMock) SetResourceDrv(*Resource) error { +func (dbM *DataDBMock) SetResourceDrv(r *Resource) error { + if dbM.SetResourceDrvF != nil { + return dbM.SetResourceDrvF(r) + } return utils.ErrNotImplemented } diff --git a/engine/z_resources_test.go b/engine/z_resources_test.go index fdb91075b..08f9ada10 100644 --- a/engine/z_resources_test.go +++ b/engine/z_resources_test.go @@ -3388,7 +3388,7 @@ func TestResourcesStoreResourceNotDirty(t *testing.T) { err := rS.StoreResource(r) if err != nil { - t.Errorf("\nexpected nil, received %+v", err) + t.Error(err) } } @@ -3404,7 +3404,7 @@ func TestResourcesStoreResourceOK(t *testing.T) { err := rS.StoreResource(r) if err != nil { - t.Errorf("\nexpected nil, received %+v", err) + t.Error(err) } if *r.dirty != false { @@ -3412,31 +3412,55 @@ func TestResourcesStoreResourceOK(t *testing.T) { } } -// func TestResourcesStoreResource2(t *testing.T) { -// tmp := Cache -// defer func() { -// Cache = tmp -// }() +func TestResourcesStoreResourceErrCache(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() -// Cache.Clear(nil) -// cfg := config.NewDefaultCGRConfig() -// rS := &ResourceService{ -// dm: NewDataManager(NewInternalDB(nil, nil, true), cfg.CacheCfg(), nil), -// } -// r := &Resource{ -// dirty: utils.BoolPointer(true), -// } + utils.Logger.SetLogLevel(6) + utils.Logger.SetSyslog(nil) + defer func() { + utils.Logger.SetLogLevel(0) + }() -// err := rS.StoreResource(r) + var buf bytes.Buffer + log.SetOutput(&buf) + defer func() { + log.SetOutput(os.Stderr) + }() -// if err != nil { -// t.Errorf("\nexpected nil, received %+v", err) -// } + cfg := config.NewDefaultCGRConfig() + dm := NewDataManager(&DataDBMock{ + SetResourceDrvF: func(r *Resource) error { + return nil + }}, cfg.CacheCfg(), nil) + rS := NewResourceService(dm, cfg, nil, nil) + Cache = NewCacheS(cfg, dm, nil) + r := &Resource{ + Tenant: "cgrates.org", + ID: "RES1", + dirty: utils.BoolPointer(true), + } + Cache.Set(utils.CacheResources, r.TenantID(), r, nil, true, "") -// if *r.dirty != false { -// t.Errorf("\nexpected false, received %+v", *r.dirty) -// } -// } + explog := `CGRateS <> [WARNING] failed caching Resource with ID: cgrates.org:RES1, error: NOT_IMPLEMENTED +` + if err := rS.StoreResource(r); err == nil || + err.Error() != utils.ErrNotImplemented.Error() { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotImplemented, err) + } + + if *r.dirty != true { + t.Errorf("\nexpected true, received %+v", *r.dirty) + } + + rcvlog := buf.String()[20:] + + if rcvlog != explog { + t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", explog, rcvlog) + } +} func TestResourcesAllocateResourceEmptyKey(t *testing.T) { rs := Resources{ @@ -3765,4 +3789,632 @@ func TestResourcesUpdateResource(t *testing.T) { if _, err := dm.GetResource(res.Tenant, res.ID, false, false, utils.NonTransactional); err != utils.ErrNotFound { t.Fatal(err) } + + dm.DataDB().Flush(utils.EmptyString) +} + +func TestResourcesV1ResourcesForEventOK(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + + Cache.Clear(nil) + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, true) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + Cache = NewCacheS(cfg, dm, nil) + rsPrf := &ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ThresholdIDs: []string{utils.MetaNone}, + AllocationMessage: "Approved", + Weight: 10, + Limit: 10, + UsageTTL: time.Minute, + } + rs := &Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + } + err := dm.SetResourceProfile(rsPrf, true) + if err != nil { + t.Error(err) + } + err = dm.SetResource(rs) + if err != nil { + t.Error(err) + } + + fltrs := NewFilterS(cfg, nil, dm) + rS := NewResourceService(dm, cfg, fltrs, nil) + + args := utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + ID: "ResourcesForEventTest", + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + }, + UsageID: "RU_TEST1", + } + + exp := Resources{ + { + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + }, + } + var reply Resources + if err := rS.V1ResourcesForEvent(args, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, exp) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", + utils.ToJSON(exp), utils.ToJSON(reply)) + } +} + +func TestResourcesV1ResourcesForEventNotFound(t *testing.T) { + Cache.Clear(nil) + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, true) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + rsPrf := &ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ThresholdIDs: []string{utils.MetaNone}, + Weight: 10, + Limit: 10, + UsageTTL: time.Minute, + } + rs := &Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + } + err := dm.SetResourceProfile(rsPrf, true) + if err != nil { + t.Error(err) + } + err = dm.SetResource(rs) + if err != nil { + t.Error(err) + } + + fltrs := NewFilterS(cfg, nil, dm) + rS := NewResourceService(dm, cfg, fltrs, nil) + + args := utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "ResourcesForEventTest", + Event: map[string]interface{}{ + utils.AccountField: "1002", + }, + }, + UsageID: "RU_TEST1", + } + + var reply Resources + if err := rS.V1ResourcesForEvent(args, &reply); err == nil || + err.Error() != utils.ErrNotFound.Error() { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) + } +} + +func TestResourcesV1ResourcesForEventMissingParameters(t *testing.T) { + Cache.Clear(nil) + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, true) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + rsPrf := &ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ThresholdIDs: []string{utils.MetaNone}, + Weight: 10, + Limit: 10, + UsageTTL: time.Minute, + } + rs := &Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + } + err := dm.SetResourceProfile(rsPrf, true) + if err != nil { + t.Error(err) + } + err = dm.SetResource(rs) + if err != nil { + t.Error(err) + } + + fltrs := NewFilterS(cfg, nil, dm) + rS := NewResourceService(dm, cfg, fltrs, nil) + + args := utils.ArgRSv1ResourceUsage{ + UsageID: "RU_TEST1", + } + + experr := `MANDATORY_IE_MISSING: [Event]` + var reply Resources + if err := rS.V1ResourcesForEvent(args, &reply); err == nil || + err.Error() != experr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err) + } + + args = utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + }, + UsageID: "RU_TEST2", + } + + experr = `MANDATORY_IE_MISSING: [ID]` + if err := rS.V1ResourcesForEvent(args, &reply); err == nil || + err.Error() != experr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err) + } + + args = utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "ResourcesForEventTest", + }, + UsageID: "RU_TEST3", + } + + experr = `MANDATORY_IE_MISSING: [Event]` + if err := rS.V1ResourcesForEvent(args, &reply); err == nil || + err.Error() != experr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err) + } + + args = utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "ResourcesForEventTest", + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + }, + } + + experr = `MANDATORY_IE_MISSING: [UsageID]` + if err := rS.V1ResourcesForEvent(args, &reply); err == nil || + err.Error() != experr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err) + } +} + +func TestResourcesV1ResourcesForEventCacheReplyExists(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + + Cache.Clear(nil) + cfg := config.NewDefaultCGRConfig() + cfg.CacheCfg().Partitions[utils.CacheRPCResponses].Limit = 1 + config.SetCgrConfig(cfg) + data := NewInternalDB(nil, nil, true) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + Cache = NewCacheS(cfg, dm, nil) + cacheKey := utils.ConcatenatedKey(utils.ResourceSv1GetResourcesForEvent, + utils.ConcatenatedKey("cgrates.org", "ResourcesForEventTest")) + rsPrf := &ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ThresholdIDs: []string{utils.MetaNone}, + AllocationMessage: "Approved", + Weight: 10, + Limit: 10, + UsageTTL: time.Minute, + } + rs := &Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + } + err := dm.SetResourceProfile(rsPrf, true) + if err != nil { + t.Error(err) + } + err = dm.SetResource(rs) + if err != nil { + t.Error(err) + } + + fltrs := NewFilterS(cfg, nil, dm) + rS := NewResourceService(dm, cfg, fltrs, nil) + + args := utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + ID: "ResourcesForEventTest", + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + }, + UsageID: "RU_TEST1", + } + + cacheReply := Resources{ + { + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + }, + } + Cache.Set(utils.CacheRPCResponses, cacheKey, + &utils.CachedRPCResponse{Result: &cacheReply, Error: nil}, + nil, true, utils.NonTransactional) + var reply Resources + if err := rS.V1ResourcesForEvent(args, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, cacheReply) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", + utils.ToJSON(cacheReply), utils.ToJSON(reply)) + } + + config.SetCgrConfig(config.NewDefaultCGRConfig()) +} + +func TestResourcesV1ResourcesForEventCacheReplySet(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + + Cache.Clear(nil) + cfg := config.NewDefaultCGRConfig() + cfg.CacheCfg().Partitions[utils.CacheRPCResponses].Limit = 1 + config.SetCgrConfig(cfg) + data := NewInternalDB(nil, nil, true) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + Cache = NewCacheS(cfg, dm, nil) + cacheKey := utils.ConcatenatedKey(utils.ResourceSv1GetResourcesForEvent, + utils.ConcatenatedKey("cgrates.org", "ResourcesForEventTest")) + rsPrf := &ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ThresholdIDs: []string{utils.MetaNone}, + AllocationMessage: "Approved", + Weight: 10, + Limit: 10, + UsageTTL: time.Minute, + } + rs := &Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + } + err := dm.SetResourceProfile(rsPrf, true) + if err != nil { + t.Error(err) + } + err = dm.SetResource(rs) + if err != nil { + t.Error(err) + } + + fltrs := NewFilterS(cfg, nil, dm) + rS := NewResourceService(dm, cfg, fltrs, nil) + + args := utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + ID: "ResourcesForEventTest", + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + }, + UsageID: "RU_TEST1", + } + + exp := Resources{ + { + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + }, + } + var reply Resources + if err := rS.V1ResourcesForEvent(args, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, exp) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", + utils.ToJSON(exp), utils.ToJSON(reply)) + } + + if itm, has := Cache.Get(utils.CacheRPCResponses, cacheKey); has { + resp := itm.(*utils.CachedRPCResponse) + if !reflect.DeepEqual(*resp.Result.(*Resources), exp) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, *resp.Result.(*Resources)) + } + } + + config.SetCgrConfig(config.NewDefaultCGRConfig()) +} + +func TestResourcesV1GetResourceOK(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + + Cache.Clear(nil) + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, true) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + Cache = NewCacheS(cfg, dm, nil) + + rsPrf := &ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ThresholdIDs: []string{utils.MetaNone}, + AllocationMessage: "Approved", + Weight: 10, + Limit: 10, + UsageTTL: time.Minute, + } + rs := &Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + } + err := dm.SetResource(rs) + if err != nil { + t.Error(err) + } + + fltrs := NewFilterS(cfg, nil, dm) + rS := NewResourceService(dm, cfg, fltrs, nil) + + exp := Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + } + + args := &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + ID: "RES1", + }, + } + var reply Resource + if err := rS.V1GetResource(args, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, exp) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", + utils.ToJSON(exp), utils.ToJSON(reply)) + } +} + +func TestResourcesV1GetResourceNotFound(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + + Cache.Clear(nil) + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, true) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + Cache = NewCacheS(cfg, dm, nil) + + rsPrf := &ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ThresholdIDs: []string{utils.MetaNone}, + AllocationMessage: "Approved", + Weight: 10, + Limit: 10, + UsageTTL: time.Minute, + } + rs := &Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + } + err := dm.SetResource(rs) + if err != nil { + t.Error(err) + } + + fltrs := NewFilterS(cfg, nil, dm) + rS := NewResourceService(dm, cfg, fltrs, nil) + + args := &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: "cgrates.org", + ID: "RES2", + }, + } + var reply Resource + if err := rS.V1GetResource(args, &reply); err == nil || + err.Error() != utils.ErrNotFound.Error() { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) + } +} + +func TestResourcesV1GetResourceMissingParameters(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + + Cache.Clear(nil) + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, true) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + Cache = NewCacheS(cfg, dm, nil) + + rsPrf := &ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ThresholdIDs: []string{utils.MetaNone}, + AllocationMessage: "Approved", + Weight: 10, + Limit: 10, + UsageTTL: time.Minute, + } + rs := &Resource{ + rPrf: rsPrf, + Tenant: "cgrates.org", + ID: "RES1", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 10, + }, + }, + dirty: utils.BoolPointer(false), + tUsage: utils.Float64Pointer(10), + ttl: utils.DurationPointer(time.Minute), + TTLIdx: []string{}, + } + err := dm.SetResource(rs) + if err != nil { + t.Error(err) + } + + fltrs := NewFilterS(cfg, nil, dm) + rS := NewResourceService(dm, cfg, fltrs, nil) + + args := &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{}, + } + + experr := `MANDATORY_IE_MISSING: [ID]` + var reply Resource + if err := rS.V1GetResource(args, &reply); err == nil || + err.Error() != experr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err) + } }