diff --git a/apier/v1/debit_test.go b/apier/v1/debit_test.go
index 01a63ab3b..00c3f16a0 100644
--- a/apier/v1/debit_test.go
+++ b/apier/v1/debit_test.go
@@ -39,7 +39,6 @@ func init() {
cfg, _ := config.NewDefaultCGRConfig()
responder := new(engine.Responder)
dm = engine.NewDataManager(apierDebitStorage)
-
engine.SetDataStorage(dm)
apierDebit = &ApierV1{
DataManager: dm,
diff --git a/apier/v1/filters.go b/apier/v1/filters.go
new file mode 100644
index 000000000..4b5874583
--- /dev/null
+++ b/apier/v1/filters.go
@@ -0,0 +1,67 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package v1
+
+import (
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+//SetFilterProfile add a new FilterProfile
+func (self *ApierV1) SetFilterProfile(attrs *engine.FilterProfile, reply *string) error {
+ if missing := utils.MissingStructFields(attrs, []string{"Tenant", "ID"}); len(missing) != 0 {
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if err := self.DataManager.DataDB().SetFilterProfile(attrs); err != nil {
+ return utils.APIErrorHandler(err)
+ }
+ *reply = utils.OK
+ return nil
+}
+
+//GetFilterProfile returns a FilterProfile
+func (self *ApierV1) GetFilterProfile(arg utils.TenantID, reply *engine.FilterProfile) error {
+ if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if fltr, err := self.DataManager.DataDB().GetFilterProfile(arg.Tenant, arg.ID, true, utils.NonTransactional); err != nil {
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
+ } else {
+ *reply = *fltr
+ }
+ return nil
+}
+
+//RemFilterProfile remove a specific filter profile
+func (self *ApierV1) RemFilterProfile(arg utils.TenantID, reply *string) error {
+ if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing
+ return utils.NewErrMandatoryIeMissing(missing...)
+ }
+ if err := self.DataManager.DataDB().RemoveFilterProfile(arg.Tenant, arg.ID, utils.NonTransactional); err != nil {
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
+ }
+ *reply = utils.OK
+ return nil
+}
diff --git a/apier/v1/filters_it_test.go b/apier/v1/filters_it_test.go
new file mode 100644
index 000000000..95465d112
--- /dev/null
+++ b/apier/v1/filters_it_test.go
@@ -0,0 +1,199 @@
+// +build integration
+
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package v1
+
+import (
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+ "net/rpc"
+ "net/rpc/jsonrpc"
+ "path"
+ "reflect"
+ "testing"
+)
+
+var (
+ filterProfileCfgPath string
+ filterProfileCfg *config.CGRConfig
+ filterProfileRPC *rpc.Client
+ filterProfileDataDir = "/usr/share/cgrates"
+ filterProfile *engine.FilterProfile
+ filterProfileDelay int
+ filterProfileConfigDIR string //run tests for specific configuration
+)
+
+var sTestsFilterProfile = []func(t *testing.T){
+ testFilterProfileInitCfg,
+ testFilterProfileResetDataDB,
+ testFilterProfileStartEngine,
+ testFilterProfileRpcConn,
+ testFilterProfileGetFilterProfileBeforeSet,
+ testFilterProfileSetFilterProfile,
+ testFilterProfileGetFilterProfileAfterSet,
+ testFilterProfileUpdateFilterProfile,
+ testFilterProfileGetFilterProfileAfterUpdate,
+ testFilterProfileRemFilterProfile,
+ testFilterProfileGetFilterProfileAfterRemove,
+ testFilterProfileKillEngine,
+}
+
+//Test start here
+func TestFilterProfileITMySql(t *testing.T) {
+ filterProfileConfigDIR = "tutmysql"
+ for _, stest := range sTestsFilterProfile {
+ t.Run(filterProfileConfigDIR, stest)
+ }
+}
+
+func TestFilterProfileITMongo(t *testing.T) {
+ filterProfileConfigDIR = "tutmongo"
+ for _, stest := range sTestsFilterProfile {
+ t.Run(filterProfileConfigDIR, stest)
+ }
+}
+
+func TestFilterProfileITPG(t *testing.T) {
+ filterProfileConfigDIR = "tutpostgres"
+ for _, stest := range sTestsFilterProfile {
+ t.Run(filterProfileConfigDIR, stest)
+ }
+}
+
+func testFilterProfileInitCfg(t *testing.T) {
+ var err error
+ filterProfileCfgPath = path.Join(filterProfileDataDir, "conf", "samples", filterProfileConfigDIR)
+ filterProfileCfg, err = config.NewCGRConfigFromFolder(filterProfileCfgPath)
+ if err != nil {
+ t.Error(err)
+ }
+ filterProfileCfg.DataFolderPath = filterProfileDataDir // Share DataFolderPath through config towards StoreDb for Flush()
+ config.SetCgrConfig(filterProfileCfg)
+ switch filterProfileConfigDIR {
+ case "tutmongo": // Mongo needs more time to reset db, need to investigate
+ filterProfileDelay = 2000
+ default:
+ filterProfileDelay = 1000
+ }
+}
+
+// Wipe out the cdr database
+func testFilterProfileResetDataDB(t *testing.T) {
+ if err := engine.InitDataDb(filterProfileCfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Start CGR Engine
+func testFilterProfileStartEngine(t *testing.T) {
+ if _, err := engine.StopStartEngine(filterProfileCfgPath, filterProfileDelay); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Connect rpc client to rater
+func testFilterProfileRpcConn(t *testing.T) {
+ var err error
+ filterProfileRPC, err = jsonrpc.Dial("tcp", filterProfileCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func testFilterProfileGetFilterProfileBeforeSet(t *testing.T) {
+ var reply *engine.FilterProfile
+ if err := filterProfileRPC.Call("ApierV1.GetFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testFilterProfileSetFilterProfile(t *testing.T) {
+ filterProfile = &engine.FilterProfile{
+ Tenant: "cgrates.org",
+ ID: "Filter1",
+ FilterType: "*string_prefix",
+ FilterFieldName: "Account",
+ FilterFieldValues: []string{"10", "20"},
+ }
+
+ var result string
+ if err := filterProfileRPC.Call("ApierV1.SetFilterProfile", filterProfile, &result); err != nil {
+ t.Error(err)
+ } else if result != utils.OK {
+ t.Error("Unexpected reply returned", result)
+ }
+}
+
+func testFilterProfileGetFilterProfileAfterSet(t *testing.T) {
+ var reply *engine.FilterProfile
+ if err := filterProfileRPC.Call("ApierV1.GetFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(filterProfile, reply) {
+ t.Errorf("Expecting : %+v, received: %+v", filterProfile, reply)
+ }
+}
+
+func testFilterProfileUpdateFilterProfile(t *testing.T) {
+ filterProfile = &engine.FilterProfile{
+ Tenant: "cgrates.org",
+ ID: "Filter1",
+ FilterType: "*string_prefix",
+ FilterFieldName: "Destination",
+ FilterFieldValues: []string{"1001", "1002"},
+ }
+ var result string
+ if err := filterProfileRPC.Call("ApierV1.SetFilterProfile", filterProfile, &result); err != nil {
+ t.Error(err)
+ } else if result != utils.OK {
+ t.Error("Unexpected reply returned", result)
+ }
+}
+
+func testFilterProfileGetFilterProfileAfterUpdate(t *testing.T) {
+ var reply *engine.FilterProfile
+ if err := filterProfileRPC.Call("ApierV1.GetFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(filterProfile, reply) {
+ t.Errorf("Expecting : %+v, received: %+v", filterProfile, reply)
+ }
+}
+
+func testFilterProfileRemFilterProfile(t *testing.T) {
+ var resp string
+ if err := filterProfileRPC.Call("ApierV1.RemFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &resp); err != nil {
+ t.Error(err)
+ } else if resp != utils.OK {
+ t.Error("Unexpected reply returned", resp)
+ }
+}
+
+func testFilterProfileGetFilterProfileAfterRemove(t *testing.T) {
+ var reply *engine.FilterProfile
+ if err := filterProfileRPC.Call("ApierV1.GetFilterProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "Filter1"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testFilterProfileKillEngine(t *testing.T) {
+ if err := engine.KillEngine(filterProfileDelay); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/apier/v1/tpthreholds_it_test.go b/apier/v1/tpthresholds_it_test.go
similarity index 100%
rename from apier/v1/tpthreholds_it_test.go
rename to apier/v1/tpthresholds_it_test.go