diff --git a/apis/resources_it_test.go b/apis/resources_it_test.go index a5793e97c..fd2c71ed7 100644 --- a/apis/resources_it_test.go +++ b/apis/resources_it_test.go @@ -19,10 +19,14 @@ along with this program. If not, see package apis import ( + "io" + "net/http" + "net/http/httptest" "path" "reflect" "sort" "testing" + "time" "github.com/cgrates/birpc" "github.com/cgrates/birpc/context" @@ -33,6 +37,8 @@ import ( ) var ( + rsSrv *httptest.Server + rsBody []byte rsCfgPath string rsCfg *config.CGRConfig rsRPC *birpc.Client @@ -52,9 +58,9 @@ var ( testResourceSGetResourceProfileCount, testResourceSGetResourcesForEvent, testResourceSAllocateResources, - // testResourceSAuthorizeResourcesBeforeRelease, - // testResourceSReleaseResources, - // testResourceSAuthorizeResourcesAfterRelease, + testResourceSAuthorizeResourcesBeforeRelease, + testResourceSReleaseResources, + testResourceSAuthorizeResourcesAfterRelease, testResourceSRemoveResourceProfiles, testResourceSGetResourceProfilesAfterRemove, testResourceSPing, @@ -66,11 +72,13 @@ var ( testResourceSResetStorDB, testResourceSStartEngine, testResourceSRPCConn, + testResourceSStartServer, testResourceSSetActionProfile, testResourceSSetThresholdProfile, testResourceSSetResourceProfile, - // testResourceSCheckThresholdAfterResourceAllocate, - // testResourceSCheckThresholdAfterResourceRelease, + testResourceSCheckThresholdAfterResourceAllocate, + testResourceSCheckThresholdAfterResourceRelease, + testResourceSStopServer, testResourceSKillEngine, } ) @@ -78,11 +86,11 @@ var ( func TestResourceSIT(t *testing.T) { switch *dbType { case utils.MetaInternal: - rsConfigDIR = "tutinternal" + rsConfigDIR = "resources_internal" case utils.MetaMongo: - rsConfigDIR = "tutmongo" + rsConfigDIR = "resources_mongo" case utils.MetaMySQL: - rsConfigDIR = "tutmysql" + rsConfigDIR = "resources_mysql" case utils.MetaPostgres: t.SkipNow() default: @@ -364,8 +372,9 @@ func testResourceSAllocateResources(t *testing.T) { }, ID: "EventTest", }, - UsageID: "RU_Test", - Units: 6, + UsageTTL: utils.DurationPointer(time.Minute), + UsageID: "RU_Test", + Units: 6, } var reply string @@ -377,68 +386,69 @@ func testResourceSAllocateResources(t *testing.T) { } } -// func testResourceSAuthorizeResourcesBeforeRelease(t *testing.T) { -// args := &utils.ArgRSv1ResourceUsage{ -// CGREvent: &utils.CGREvent{ -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// }, -// ID: "EventTest", -// }, -// UsageID: "RU_Test", -// Units: 7, -// } +func testResourceSAuthorizeResourcesBeforeRelease(t *testing.T) { + args := &utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + ID: "EventTest", + }, + UsageID: "RU_Test", + UsageTTL: utils.DurationPointer(time.Minute), + Units: 7, + } -// var reply string -// if err := rsRPC.Call(context.Background(), utils.ResourceSv1AuthorizeResources, -// args, &reply); err != nil { -// t.Error(err) -// } else if reply != "Approved" { -// t.Error("Unexpected reply returned:", reply) -// } -// } + var reply string + if err := rsRPC.Call(context.Background(), utils.ResourceSv1AuthorizeResources, + args, &reply); err == nil || err.Error() != utils.ErrResourceUnauthorized.Error() { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrResourceUnauthorized, err) + } +} -// func testResourceSReleaseResources(t *testing.T) { -// args := &utils.ArgRSv1ResourceUsage{ -// CGREvent: &utils.CGREvent{ -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// }, -// ID: "EventTest", -// }, -// UsageID: "RU_Test", -// Units: 4, -// } -// var reply string +func testResourceSReleaseResources(t *testing.T) { + args := &utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + ID: "EventTest", + }, + UsageTTL: utils.DurationPointer(time.Minute), + UsageID: "RU_Test", + Units: 4, + } + var reply string -// if err := rsRPC.Call(context.Background(), utils.ResourceSv1ReleaseResources, -// args, &reply); err != nil { -// t.Error(err) -// } else if reply != utils.OK { -// t.Error("Unexpected reply returned:", reply) -// } -// } + if err := rsRPC.Call(context.Background(), utils.ResourceSv1ReleaseResources, + args, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Error("Unexpected reply returned:", reply) + } +} -// func testResourceSAuthorizeResourcesAfterRelease(t *testing.T) { -// args := &utils.ArgRSv1ResourceUsage{ -// CGREvent: &utils.CGREvent{ -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// }, -// ID: "EventTest", -// }, -// UsageID: "RU_Test", -// Units: 7, -// } +func testResourceSAuthorizeResourcesAfterRelease(t *testing.T) { + args := &utils.ArgRSv1ResourceUsage{ + CGREvent: &utils.CGREvent{ + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + ID: "EventTest", + }, + UsageID: "RU_Test", + UsageTTL: utils.DurationPointer(time.Minute), + Units: 7, + } -// var reply string -// if err := rsRPC.Call(context.Background(), utils.ResourceSv1AuthorizeResources, -// args, &reply); err != nil { -// t.Error(err) -// } else if reply != "Approved" { -// t.Error("Unexpected reply returned:", reply) -// } -// } + var reply string + if err := rsRPC.Call(context.Background(), utils.ResourceSv1AuthorizeResources, + args, &reply); err != nil { + t.Error(err) + } else if reply != "Approved" { + t.Error("Unexpected reply returned:", reply) + } +} func testResourceSRemoveResourceProfiles(t *testing.T) { var reply string @@ -493,15 +503,36 @@ func testResourceSPing(t *testing.T) { } } +func testResourceSStartServer(t *testing.T) { + rsSrv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var err error + rsBody, err = io.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusNotFound) + } + + r.Body.Close() + })) +} + +func testResourceSStopServer(t *testing.T) { + rsSrv.Close() +} func testResourceSSetActionProfile(t *testing.T) { actPrf := &engine.ActionProfileWithAPIOpts{ ActionProfile: &engine.ActionProfile{ - Tenant: "cgrates.org", - ID: "actPrfID", - FilterIDs: []string{"*string:~*req.Account:1001"}, + Tenant: "cgrates.org", + ID: "actPrfID", Actions: []*engine.APAction{ { - ID: "actID", + ID: "actID", + Type: utils.MetaHTTPPost, + Diktats: []*engine.APDiktat{ + { + Path: rsSrv.URL, + }, + }, + TTL: time.Duration(time.Minute), }, }, }, @@ -521,7 +552,7 @@ func testResourceSSetThresholdProfile(t *testing.T) { FilterIDs: []string{"*string:~*opts.*eventType:ResourceUpdate"}, ID: "THD_1", MaxHits: -1, - ActionProfileIDs: []string{"actID"}, + ActionProfileIDs: []string{"actPrfID"}, }, } var reply string @@ -550,6 +581,7 @@ func testResourceSSetResourceProfile(t *testing.T) { rsPrf := &engine.ResourceProfile{ Tenant: "cgrates.org", ID: "RES_1", + FilterIDs: []string{"*string:~*req.Account:1001"}, AllocationMessage: "Approved", Limit: 10, ThresholdIDs: []string{"THD_1"}, @@ -572,66 +604,72 @@ func testResourceSSetResourceProfile(t *testing.T) { } } -// func testResourceSCheckThresholdAfterResourceAllocate(t *testing.T) { -// var reply string -// argsRU := utils.ArgRSv1ResourceUsage{ -// UsageID: "RU_1", -// CGREvent: &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "EV_1", -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// }, -// }, +func testResourceSCheckThresholdAfterResourceAllocate(t *testing.T) { + var reply string + argsRU := utils.ArgRSv1ResourceUsage{ + UsageID: "RU_1", + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "EV_1", + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + }, -// Units: 1, -// } -// if err := rsRPC.Call(context.Background(), utils.ResourceSv1AllocateResources, -// argsRU, &reply); err != nil { -// t.Error(err) -// } else if reply != "Approved" { -// t.Error("Unexpected reply returned", reply) -// } + Units: 1, + } -// args := &utils.TenantID{ -// Tenant: "cgrates.org", -// ID: "THD_1", -// } -// var result *engine.Threshold -// if err := rsRPC.Call(context.Background(), utils.ThresholdSv1GetThreshold, -// args, &result); err != nil { -// t.Error(err) -// } else if result.Hits != 1 { -// t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", 1, result.Hits) -// } -// } + expBody := `{"*opts":{"*eventType":"ResourceUpdate"},"*req":{"EventType":"ResourceUpdate","ResourceID":"RES_1","Usage":0}}` + if err := rsRPC.Call(context.Background(), utils.ResourceSv1AllocateResources, + argsRU, &reply); err != nil { + t.Error(err) + } else if reply != "Approved" { + t.Error("Unexpected reply returned", reply) + } -// func testResourceSCheckThresholdAfterResourceRelease(t *testing.T) { -// argsRU := &utils.ArgRSv1ResourceUsage{ -// UsageID: "RU_1", -// CGREvent: &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "EV_1", -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// }, -// }, -// } -// var reply string -// if err := rsRPC.Call(context.Background(), utils.ResourceSv1ReleaseResources, -// argsRU, &reply); err != nil { -// t.Error(err) -// } + if expBody != string(rsBody) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expBody, rsBody) + } -// args := &utils.TenantID{ -// Tenant: "cgrates.org", -// ID: "THD_1", -// } -// var result *engine.Threshold -// if err := rsRPC.Call(context.Background(), utils.ThresholdSv1GetThreshold, -// args, &result); err != nil { -// t.Error(err) -// } else if result.Hits != 2 { -// t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", 2, result.Hits) -// } -// } + args := &utils.TenantID{ + Tenant: "cgrates.org", + ID: "THD_1", + } + var result *engine.Threshold + if err := rsRPC.Call(context.Background(), utils.ThresholdSv1GetThreshold, + args, &result); err != nil { + t.Error(err) + } else if result.Hits != 1 { + t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", 1, result.Hits) + } +} + +func testResourceSCheckThresholdAfterResourceRelease(t *testing.T) { + argsRU := &utils.ArgRSv1ResourceUsage{ + UsageID: "RU_1", + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "EV_1", + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + }, + } + var reply string + if err := rsRPC.Call(context.Background(), utils.ResourceSv1ReleaseResources, + argsRU, &reply); err != nil { + t.Error(err) + } + + args := &utils.TenantID{ + Tenant: "cgrates.org", + ID: "THD_1", + } + var result *engine.Threshold + if err := rsRPC.Call(context.Background(), utils.ThresholdSv1GetThreshold, + args, &result); err != nil { + t.Error(err) + } else if result.Hits != 2 { + t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", 2, result.Hits) + } +} diff --git a/data/conf/samples/resources_internal/cgrates.json b/data/conf/samples/resources_internal/cgrates.json new file mode 100644 index 000000000..f97c10be8 --- /dev/null +++ b/data/conf/samples/resources_internal/cgrates.json @@ -0,0 +1,34 @@ +{ + // CGRateS Configuration file + // will be used in apis/resources_it_test.go + + "general": { + "log_level": 7, + }, + + "data_db": { + "db_type": "*internal", + }, + + "stor_db": { + "db_type": "*internal", + }, + + "actions": { + "enabled": true, + }, + + "thresholds": { + "enabled": true, + "actions_conns": ["*internal"], + }, + + "resources": { + "enabled": true, + "thresholds_conns": ["*internal"], + }, + + "admins": { + "enabled": true, + }, + } \ No newline at end of file diff --git a/data/conf/samples/resources_mongo/cgrates.json b/data/conf/samples/resources_mongo/cgrates.json new file mode 100644 index 000000000..e485e4914 --- /dev/null +++ b/data/conf/samples/resources_mongo/cgrates.json @@ -0,0 +1,38 @@ +{ + // CGRateS Configuration file + // will be used in apis/resources_it_test.go + + "general": { + "log_level": 7, + }, + + "data_db": { + "db_type": "mongo", + "db_name": "10", + "db_port": 27017, + }, + + "stor_db": { + "db_type": "mongo", + "db_name": "cgrates", + "db_port": 27017, + }, + + "actions": { + "enabled": true, + }, + + "thresholds": { + "enabled": true, + "actions_conns": ["*internal"], + }, + + "resources": { + "enabled": true, + "thresholds_conns": ["*internal"], + }, + + "admins": { + "enabled": true, + } + } \ No newline at end of file diff --git a/data/conf/samples/resources_mysql/cgrates.json b/data/conf/samples/resources_mysql/cgrates.json new file mode 100644 index 000000000..11df53337 --- /dev/null +++ b/data/conf/samples/resources_mysql/cgrates.json @@ -0,0 +1,35 @@ +{ + // CGRateS Configuration file + // will be used in apis/resources_it_test.go + "general": { + "log_level": 7, + }, + + "data_db": { // database used to store runtime data (eg: accounts, cdr stats) + "db_type": "redis", // data_db type: + "db_port": 6379, // data_db port to reach the database + "db_name": "10", // data_db database name to connect to + }, + + "stor_db": { + "db_password": "CGRateS.org", + }, + + "actions": { + "enabled": true, + }, + + "thresholds": { + "enabled": true, + "actions_conns": ["*localhost"], + }, + + "resources": { + "enabled": true, + "thresholds_conns": ["*internal"], + }, + + "admins": { + "enabled": true, + } + } \ No newline at end of file