diff --git a/apier/v1/tpaccountactions.go b/apier/v1/tpaccountactions.go
index 796d49b7d..87045899e 100644
--- a/apier/v1/tpaccountactions.go
+++ b/apier/v1/tpaccountactions.go
@@ -51,9 +51,10 @@ func (self *ApierV1) GetTPAccountActionsByLoadId(attrs utils.TPAccountActions, r
return utils.NewErrMandatoryIeMissing(missing...)
}
if aas, err := self.StorDb.GetTPAccountActions(&attrs); err != nil {
- return utils.NewErrServerError(err)
- } else if len(aas) == 0 {
- return utils.ErrNotFound
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
} else {
reply = &aas
}
@@ -75,9 +76,10 @@ func (self *ApierV1) GetTPAccountActions(attrs AttrGetTPAccountActions, reply *u
return err
}
if aas, err := self.StorDb.GetTPAccountActions(filter); err != nil {
- return utils.NewErrServerError(err)
- } else if len(aas) == 0 {
- return utils.ErrNotFound
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
} else {
*reply = *aas[0]
}
diff --git a/apier/v1/tpaccountactions_it_test.go b/apier/v1/tpaccountactions_it_test.go
new file mode 100644
index 000000000..d0dbe4a18
--- /dev/null
+++ b/apier/v1/tpaccountactions_it_test.go
@@ -0,0 +1,212 @@
+// +build offline_tp
+
+/*
+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 (
+ tpAccActionsCfgPath string
+ tpAccActionsCfg *config.CGRConfig
+ tpAccActionsRPC *rpc.Client
+ tpAccActionsDataDir = "/usr/share/cgrates"
+ tpAccActions *utils.TPAccountActions
+ tpAccActionsDelay int
+ tpAccActionsConfigDIR string //run tests for specific configuration
+ tpAccActionID = "ID:cgrates.org:1001"
+)
+
+var sTestsTPAccActions = []func(t *testing.T){
+ testTPAccActionsInitCfg,
+ testTPAccActionsResetStorDb,
+ testTPAccActionsStartEngine,
+ testTPAccActionsRpcConn,
+ testTPAccActionsGetTPAccActionBeforeSet,
+ testTPAccActionsSetTPAccAction,
+ testTPAccActionsGetTPAccActionAfterSet,
+ testTPAccActionsGetTPAccActionIds,
+ testTPAccActionsUpdateTPAccAction,
+ testTPAccActionsGetTPAccActionAfterUpdate,
+ testTPAccActionsRemTPAccAction,
+ testTPAccActionsGetTPAccActionAfterRemove,
+ testTPAccActionsKillEngine,
+}
+
+//Test start here
+func TestTPAccActionsITMySql(t *testing.T) {
+ tpAccActionsConfigDIR = "tutmysql"
+ for _, stest := range sTestsTPAccActions {
+ t.Run(tpAccActionsConfigDIR, stest)
+ }
+}
+
+func TestTPAccActionsITMongo(t *testing.T) {
+ tpAccActionsConfigDIR = "tutmongo"
+ for _, stest := range sTestsTPAccActions {
+ t.Run(tpAccActionsConfigDIR, stest)
+ }
+}
+
+func TestTTPAccActionsITPG(t *testing.T) {
+ tpAccActionsConfigDIR = "tutpostgres"
+ for _, stest := range sTestsTPAccActions {
+ t.Run(tpAccActionsConfigDIR, stest)
+ }
+}
+
+func testTPAccActionsInitCfg(t *testing.T) {
+ var err error
+ tpAccActionsCfgPath = path.Join(tpAccActionsDataDir, "conf", "samples", tpAccActionsConfigDIR)
+ tpAccActionsCfg, err = config.NewCGRConfigFromFolder(tpAccActionsCfgPath)
+ if err != nil {
+ t.Error(err)
+ }
+ tpAccActionsCfg.DataFolderPath = tpAccActionsDataDir // Share DataFolderPath through config towards StoreDb for Flush()
+ config.SetCgrConfig(tpAccActionsCfg)
+ switch tpAccActionsConfigDIR {
+ case "tutmongo": // Mongo needs more time to reset db, need to investigate
+ tpAccActionsDelay = 2000
+ default:
+ tpAccActionsDelay = 1000
+ }
+}
+
+// Wipe out the cdr database
+func testTPAccActionsResetStorDb(t *testing.T) {
+ if err := engine.InitStorDb(tpAccActionsCfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Start CGR Engine
+func testTPAccActionsStartEngine(t *testing.T) {
+ if _, err := engine.StopStartEngine(tpAccActionsCfgPath, tpAccActionsDelay); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Connect rpc client to rater
+func testTPAccActionsRpcConn(t *testing.T) {
+ var err error
+ tpAccActionsRPC, err = jsonrpc.Dial("tcp", tpAccActionsCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func testTPAccActionsGetTPAccActionBeforeSet(t *testing.T) {
+ var reply *utils.TPAccountActions
+ if err := tpAccActionsRPC.Call("ApierV1.GetTPAccountActions", &AttrGetTPAccountActions{TPid: "TPAcc", AccountActionsId: tpAccActionID}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+
+}
+
+func testTPAccActionsSetTPAccAction(t *testing.T) {
+ tpAccActions = &utils.TPAccountActions{
+ TPid: "TPAcc",
+ LoadId: "ID",
+ Tenant: "cgrates.org",
+ Account: "1001",
+ ActionPlanId: "PREPAID_10",
+ ActionTriggersId: "STANDARD_TRIGGERS",
+ AllowNegative: true,
+ Disabled: false,
+ }
+ var result string
+ if err := tpAccActionsRPC.Call("ApierV1.SetTPAccountActions", tpAccActions, &result); err != nil {
+ t.Error(err)
+ } else if result != utils.OK {
+ t.Error("Unexpected reply returned", result)
+ }
+}
+
+func testTPAccActionsGetTPAccActionAfterSet(t *testing.T) {
+ var reply *utils.TPAccountActions
+ if err := tpAccActionsRPC.Call("ApierV1.GetTPAccountActions", &AttrGetTPAccountActions{TPid: "TPAcc", AccountActionsId: tpAccActionID}, &reply); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(tpAccActions, reply) {
+ t.Errorf("Expecting : %+v, received: %+v", tpAccActions, reply)
+ }
+}
+
+func testTPAccActionsGetTPAccActionIds(t *testing.T) {
+ var result []string
+ expectedTPID := []string{"ID"}
+ if err := tpAccActionsRPC.Call("ApierV1.GetTPAccountActionLoadIds", &AttrGetTPAccountActionIds{TPid: "TPAcc"}, &result); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(expectedTPID, result) {
+ t.Errorf("Expecting: %+v, received: %+v", expectedTPID, result)
+ }
+
+}
+
+func testTPAccActionsUpdateTPAccAction(t *testing.T) {
+ tpAccActions.ActionPlanId = "PlanOne"
+ var result string
+ if err := tpAccActionsRPC.Call("ApierV1.SetTPAccountActions", tpAccActions, &result); err != nil {
+ t.Error(err)
+ } else if result != utils.OK {
+ t.Error("Unexpected reply returned", result)
+ }
+
+}
+
+func testTPAccActionsGetTPAccActionAfterUpdate(t *testing.T) {
+ var reply *utils.TPAccountActions
+ if err := tpAccActionsRPC.Call("ApierV1.GetTPAccountActions", &AttrGetTPAccountActions{TPid: "TPAcc", AccountActionsId: tpAccActionID}, &reply); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(tpAccActions, reply) {
+ t.Errorf("Expecting : %+v, received: %+v", tpAccActions, reply)
+ }
+
+}
+
+func testTPAccActionsRemTPAccAction(t *testing.T) {
+ var resp string
+ if err := tpAccActionsRPC.Call("ApierV1.RemTPAccountActions", &AttrGetTPAccountActions{TPid: "TPAcc", AccountActionsId: tpAccActionID}, &resp); err != nil {
+ t.Error(err)
+ } else if resp != utils.OK {
+ t.Error("Unexpected reply returned", resp)
+ }
+
+}
+
+func testTPAccActionsGetTPAccActionAfterRemove(t *testing.T) {
+ var reply *utils.TPAccountActions
+ if err := tpAccActionsRPC.Call("ApierV1.GetTPAccountActions", &AttrGetTPAccountActions{TPid: "TPAcc", AccountActionsId: tpAccActionID}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testTPAccActionsKillEngine(t *testing.T) {
+ if err := engine.KillEngine(tpDestinationDelay); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/apier/v1/tpactionplans.go b/apier/v1/tpactionplans.go
index a94951298..e28e57ace 100644
--- a/apier/v1/tpactionplans.go
+++ b/apier/v1/tpactionplans.go
@@ -53,9 +53,10 @@ func (self *ApierV1) GetTPActionPlan(attrs AttrGetTPActionPlan, reply *utils.TPA
return utils.NewErrMandatoryIeMissing(missing...)
}
if aps, err := self.StorDb.GetTPActionPlans(attrs.TPid, attrs.ID); err != nil {
- return utils.NewErrServerError(err)
- } else if len(aps) == 0 {
- return utils.ErrNotFound
+ if err.Error() != utils.ErrNotFound.Error() {
+ err = utils.NewErrServerError(err)
+ }
+ return err
} else {
*reply = *aps[0]
}
diff --git a/apier/v1/tpactionplans_it_test.go b/apier/v1/tpactionplans_it_test.go
new file mode 100644
index 000000000..05b594159
--- /dev/null
+++ b/apier/v1/tpactionplans_it_test.go
@@ -0,0 +1,241 @@
+// +build offline_tp
+
+/*
+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 (
+ tpAccPlansCfgPath string
+ tpAccPlansCfg *config.CGRConfig
+ tpAccPlansRPC *rpc.Client
+ tpAccPlansDataDir = "/usr/share/cgrates"
+ tpAccPlan *utils.TPActionPlan
+ tpAccPlansDelay int
+ tpAccPlansConfigDIR string //run tests for specific configuration
+
+)
+
+var sTestsTPAccPlans = []func(t *testing.T){
+ testTPAccPlansInitCfg,
+ testTPAccPlansResetStorDb,
+ testTPAccPlansStartEngine,
+ testTPAccPlansRpcConn,
+ testTPAccPlansGetTPAccPlanBeforeSet,
+ testTPAccPlansSetTPAccPlan,
+ testTPAccPlansGetTPAccPlanAfterSet,
+ testTPAccPlansGetTPAccPlanIds,
+ testTPAccPlansUpdateTPAccPlan,
+ testTPAccPlansGetTPAccPlanAfterUpdate,
+ testTPAccPlansRemTPAccPlan,
+ testTPAccPlansGetTPAccPlanAfterRemove,
+ testTPAccPlansKillEngine,
+}
+
+//Test start here
+func TestTPAccPlansITMySql(t *testing.T) {
+ tpAccPlansConfigDIR = "tutmysql"
+ for _, stest := range sTestsTPAccPlans {
+ t.Run(tpAccPlansConfigDIR, stest)
+ }
+}
+
+func TestTPAccPlansITMongo(t *testing.T) {
+ tpAccPlansConfigDIR = "tutmongo"
+ for _, stest := range sTestsTPAccPlans {
+ t.Run(tpAccPlansConfigDIR, stest)
+ }
+}
+
+func TestTPAccPlansITPG(t *testing.T) {
+ tpAccPlansConfigDIR = "tutpostgres"
+ for _, stest := range sTestsTPAccPlans {
+ t.Run(tpAccPlansConfigDIR, stest)
+ }
+}
+
+func testTPAccPlansInitCfg(t *testing.T) {
+ var err error
+ tpAccPlansCfgPath = path.Join(tpAccPlansDataDir, "conf", "samples", tpAccPlansConfigDIR)
+ tpAccPlansCfg, err = config.NewCGRConfigFromFolder(tpAccPlansCfgPath)
+ if err != nil {
+ t.Error(err)
+ }
+ tpAccPlansCfg.DataFolderPath = tpAccPlansDataDir // Share DataFolderPath through config towards StoreDb for Flush()
+ config.SetCgrConfig(tpAccPlansCfg)
+ switch tpAccPlansConfigDIR {
+ case "tutmongo": // Mongo needs more time to reset db, need to investigate
+ tpAccPlansDelay = 2000
+ default:
+ tpAccPlansDelay = 1000
+ }
+}
+
+// Wipe out the cdr database
+func testTPAccPlansResetStorDb(t *testing.T) {
+ if err := engine.InitStorDb(tpAccPlansCfg); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Start CGR Engine
+func testTPAccPlansStartEngine(t *testing.T) {
+ if _, err := engine.StopStartEngine(tpAccPlansCfgPath, tpAccPlansDelay); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Connect rpc client to rater
+func testTPAccPlansRpcConn(t *testing.T) {
+ var err error
+ tpAccPlansRPC, err = jsonrpc.Dial("tcp", tpAccPlansCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func testTPAccPlansGetTPAccPlanBeforeSet(t *testing.T) {
+ var reply *utils.TPActionPlan
+ if err := tpAccPlansRPC.Call("ApierV1.GetTPActionPlan", &AttrGetTPActionPlan{TPid: "TPAcc", ID: "ID"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testTPAccPlansSetTPAccPlan(t *testing.T) {
+ tpAccPlan = &utils.TPActionPlan{
+ TPid: "TPAcc",
+ ID: "ID",
+ ActionPlan: []*utils.TPActionTiming{
+ &utils.TPActionTiming{
+ ActionsId: "AccId",
+ TimingId: "TimingID",
+ Weight: 10,
+ },
+ &utils.TPActionTiming{
+ ActionsId: "AccId2",
+ TimingId: "TimingID2",
+ Weight: 11,
+ },
+ },
+ }
+ var result string
+ if err := tpAccPlansRPC.Call("ApierV1.SetTPActionPlan", tpAccPlan, &result); err != nil {
+ t.Error(err)
+ } else if result != utils.OK {
+ t.Error("Unexpected reply returned", result)
+ }
+}
+
+func testTPAccPlansGetTPAccPlanAfterSet(t *testing.T) {
+ var reply *utils.TPActionPlan
+ if err := tpAccPlansRPC.Call("ApierV1.GetTPActionPlan", &AttrGetTPActionPlan{TPid: "TPAcc", ID: "ID"}, &reply); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(tpAccPlan.TPid, reply.TPid) {
+ t.Errorf("Expecting : %+v, received: %+v", tpAccPlan.TPid, reply.TPid)
+ } else if !reflect.DeepEqual(tpAccPlan.ID, reply.ID) {
+ t.Errorf("Expecting : %+v, received: %+v", tpAccPlan.ID, reply.ID)
+ } else if !reflect.DeepEqual(len(tpAccPlan.ActionPlan), len(reply.ActionPlan)) {
+ t.Errorf("Expecting : %+v, received: %+v", len(tpAccPlan.ActionPlan), len(reply.ActionPlan))
+ }
+}
+
+func testTPAccPlansGetTPAccPlanIds(t *testing.T) {
+ var result []string
+ expectedTPID := []string{"ID"}
+ if err := tpAccPlansRPC.Call("ApierV1.GetTPActionPlanIds", &AttrGetTPActionPlanIds{TPid: "TPAcc"}, &result); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(expectedTPID, result) {
+ t.Errorf("Expecting: %+v, received: %+v", expectedTPID, result)
+ }
+
+}
+
+func testTPAccPlansUpdateTPAccPlan(t *testing.T) {
+ tpAccPlan.ActionPlan = []*utils.TPActionTiming{
+ &utils.TPActionTiming{
+ ActionsId: "AccId",
+ TimingId: "TimingID",
+ Weight: 10,
+ },
+ &utils.TPActionTiming{
+ ActionsId: "AccId2",
+ TimingId: "TimingID2",
+ Weight: 11,
+ },
+ &utils.TPActionTiming{
+ ActionsId: "AccId3",
+ TimingId: "TimingID3",
+ Weight: 12,
+ },
+ }
+ var result string
+ if err := tpAccPlansRPC.Call("ApierV1.SetTPActionPlan", tpAccPlan, &result); err != nil {
+ t.Error(err)
+ } else if result != utils.OK {
+ t.Error("Unexpected reply returned", result)
+ }
+
+}
+
+func testTPAccPlansGetTPAccPlanAfterUpdate(t *testing.T) {
+ var reply *utils.TPActionPlan
+ if err := tpAccPlansRPC.Call("ApierV1.GetTPActionPlan", &AttrGetTPActionPlan{TPid: "TPAcc", ID: "ID"}, &reply); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(tpAccPlan.TPid, reply.TPid) {
+ t.Errorf("Expecting : %+v, received: %+v", tpAccPlan.TPid, reply.TPid)
+ } else if !reflect.DeepEqual(tpAccPlan.ID, reply.ID) {
+ t.Errorf("Expecting : %+v, received: %+v", tpAccPlan.ID, reply.ID)
+ } else if !reflect.DeepEqual(len(tpAccPlan.ActionPlan), len(reply.ActionPlan)) {
+ t.Errorf("Expecting : %+v, received: %+v", len(tpAccPlan.ActionPlan), len(reply.ActionPlan))
+ }
+
+}
+
+func testTPAccPlansRemTPAccPlan(t *testing.T) {
+ var resp string
+ if err := tpAccPlansRPC.Call("ApierV1.RemTPActionPlan", &AttrGetTPActionPlan{TPid: "TPAcc", ID: "ID"}, &resp); err != nil {
+ t.Error(err)
+ } else if resp != utils.OK {
+ t.Error("Unexpected reply returned", resp)
+ }
+
+}
+
+func testTPAccPlansGetTPAccPlanAfterRemove(t *testing.T) {
+ var reply *utils.TPActionPlan
+ if err := tpAccPlansRPC.Call("ApierV1.GetTPActionPlan", &AttrGetTPActionPlan{TPid: "TPAcc", ID: "ID"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
+ t.Error(err)
+ }
+}
+
+func testTPAccPlansKillEngine(t *testing.T) {
+ if err := engine.KillEngine(tpAccPlansDelay); err != nil {
+ t.Error(err)
+ }
+}