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) + } +}