diff --git a/actions/accounts_test.go b/actions/accounts_test.go
new file mode 100644
index 000000000..3d7e11a6b
--- /dev/null
+++ b/actions/accounts_test.go
@@ -0,0 +1,137 @@
+/*
+Real-time Online/Offline Charging System (OerS) 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 actions
+
+import (
+ "testing"
+ "time"
+
+ "github.com/cgrates/rpcclient"
+
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestACExecuteAccountsSetBalance(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ internalChan := make(chan rpcclient.ClientConnector, 1)
+ connMngr := engine.NewConnManager(cfg, map[string]chan rpcclient.ClientConnector{
+ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts): internalChan,
+ })
+ apAction := &engine.APAction{
+ ID: "TestACExecuteAccounts",
+ Type: utils.MetaSetBalance,
+ Diktats: []*engine.APDiktat{
+ {
+ Path: "~*balance.TestBalance.Value",
+ Value: "\"constant;`>;q=0.7;expires=3600constant\"",
+ },
+ },
+ }
+
+ dataStorage := utils.MapStorage{
+ utils.MetaReq: map[string]interface{}{
+ utils.AccountField: "1001",
+ },
+ utils.MetaOpts: map[string]interface{}{
+ utils.Usage: 10 * time.Minute,
+ },
+ }
+
+ actCdrLG := &actSetBalance{
+ config: cfg,
+ connMgr: connMngr,
+ aCfg: apAction,
+ }
+
+ expected := "no connection with AccountS"
+ if err := actCdrLG.execute(nil, dataStorage, utils.MetaBalanceLimit); err == nil || err.Error() != expected {
+ t.Errorf("Expected %+v, received %+v", expected, err)
+ }
+
+ actCdrLG.config.ActionSCfg().AccountSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts)}
+ expected = "Closed unspilit syntax "
+ if err := actCdrLG.execute(nil, dataStorage, utils.MetaBalanceLimit); err == nil || err.Error() != expected {
+ t.Errorf("Expected %+v, received %+v", expected, err)
+ }
+
+ //invalid to parse a value from diktats
+ actCdrLG.aCfg.Diktats[0].Value = "10"
+ expected = "DISCONNECTED"
+ if err := actCdrLG.execute(nil, dataStorage, utils.MetaBalanceLimit); err == nil || err.Error() != expected {
+ t.Errorf("Expected %+v, received %+v", expected, err)
+ }
+}
+
+func TestACExecuteAccountsRemBalance(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ internalChan := make(chan rpcclient.ClientConnector, 1)
+ connMngr := engine.NewConnManager(cfg, map[string]chan rpcclient.ClientConnector{
+ utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts): internalChan,
+ })
+ apAction := &engine.APAction{
+ ID: "TestACExecuteAccountsRemBalance",
+ Type: utils.MetaSetBalance,
+ Diktats: []*engine.APDiktat{
+ {
+ Path: "~*balance.TestBalance.Value",
+ Value: "10",
+ },
+ },
+ }
+
+ actRemBal := &actRemBalance{
+ config: cfg,
+ connMgr: connMngr,
+ aCfg: apAction,
+ tnt: "cgrates.org",
+ }
+
+ expected := "no connection with AccountS"
+ if err := actRemBal.execute(nil, nil, utils.MetaRemBalance); err == nil || err.Error() != expected {
+ t.Errorf("Expected %+v, received %+v", expected, err)
+ }
+
+ actRemBal.config.ActionSCfg().AccountSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts)}
+ expected = "DISCONNECTED"
+ if err := actRemBal.execute(nil, nil, utils.MetaRemBalance); err == nil || err.Error() != expected {
+ t.Errorf("Expected %+v, received %+v", expected, err)
+ }
+}
+
+func TestACAccountsGetIDs(t *testing.T) {
+ apAction := &engine.APAction{
+ ID: "TestACExecuteAccountsRemBalance",
+ }
+
+ actRemBal := &actRemBalance{
+ aCfg: apAction,
+ }
+ if rcv := actRemBal.id(); rcv != apAction.ID {
+ t.Errorf("Expected %+v, received %+v", apAction.ID, rcv)
+ }
+
+ actSeTBal := &actSetBalance{
+ aCfg: apAction,
+ }
+ if rcv := actSeTBal.id(); rcv != apAction.ID {
+ t.Errorf("Expected %+v, received %+v", apAction.ID, rcv)
+ }
+}
diff --git a/actions/export_test.go b/actions/export_test.go
new file mode 100644
index 000000000..99c1cb003
--- /dev/null
+++ b/actions/export_test.go
@@ -0,0 +1,145 @@
+/*
+Real-time Online/Offline Charging System (OerS) 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 actions
+
+import (
+ "bytes"
+ "log"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestACHTTPPostExecute(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ apAction := &engine.APAction{
+ ID: "TEST_ACTION_HTTPPOST",
+ Type: utils.CDRLog,
+ Diktats: []*engine.APDiktat{
+ {
+ Path: "~*balance.TestBalance.Value",
+ Value: "10",
+ },
+ },
+ }
+ http := &actHTTPPost{
+ config: cfg,
+ aCfg: apAction,
+ }
+
+ dataStorage := utils.MapStorage{
+ utils.MetaReq: map[string]interface{}{
+ utils.AccountField: "1001",
+ },
+ utils.MetaOpts: map[string]interface{}{
+ utils.Usage: 10 * time.Minute,
+ },
+ }
+
+ var err error
+ utils.Logger, err = utils.Newlogger(utils.MetaStdLog, utils.EmptyString)
+ if err != nil {
+ t.Error(err)
+ }
+ utils.Logger.SetLogLevel(7)
+
+ buff := new(bytes.Buffer)
+ log.SetOutput(buff)
+
+ expected := "[WARNING] Posting to : <~*balance.TestBalance.Value>, error: "
+ if err := http.execute(nil, dataStorage, utils.EmptyString); err != nil {
+ t.Error(err)
+ } else if rcv := buff.String(); !strings.Contains(rcv, expected) {
+ t.Errorf("Expected %+v, received %+v", expected, rcv)
+ }
+
+ buff.Reset()
+
+ // channels cannot be marshaled
+ dataStorage[utils.MetaReq] = make(chan struct{}, 1)
+ expected = "json: unsupported type: chan struct {}"
+ if err := http.execute(nil, dataStorage, utils.EmptyString); err == nil || err.Error() != expected {
+ t.Errorf("Expected %+v, received %+v", expected, err)
+ }
+
+ dataStorage = utils.MapStorage{
+ utils.MetaOpts: map[string]interface{}{
+ utils.MetaAsync: 10 * time.Minute,
+ },
+ }
+ http.aCfg.Opts = make(map[string]interface{})
+ http.aCfg.Opts[utils.MetaAsync] = true
+ http.config.GeneralCfg().FailedPostsDir = utils.MetaNone
+ if err := http.execute(nil, dataStorage, utils.EmptyString); err != nil {
+ t.Error(err)
+ }
+}
+
+func TestACHTTPPostValues(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ cfg.GeneralCfg().FailedPostsDir = utils.MetaNone
+ apAction := &engine.APAction{
+ ID: "TEST_ACTION_HTTPPostValues",
+ Type: utils.MetaHTTPPost,
+ Diktats: []*engine.APDiktat{
+ {
+ Path: "~*balance.TestBalance.Value",
+ Value: "80",
+ },
+ },
+ }
+ http := &actHTTPPost{
+ config: cfg,
+ aCfg: apAction,
+ }
+ dataStorage := utils.MapStorage{
+ utils.MetaReq: map[string]interface{}{
+ utils.AccountField: 1003,
+ },
+ }
+
+ if err := http.execute(nil, dataStorage,
+ utils.EmptyString); err == nil || err != utils.ErrPartiallyExecuted {
+ t.Errorf("Expected %+v, received %+v", utils.ErrPartiallyExecuted, err)
+ }
+}
+
+func TestACHTTPPostID(t *testing.T) {
+ apAction := &engine.APAction{
+ ID: "TestACHTTPPostID",
+ Type: utils.MetaHTTPPost,
+ }
+ http := &actHTTPPost{
+ aCfg: apAction,
+ }
+ if rcv := http.id(); rcv != apAction.ID {
+ t.Errorf("Expected %+v, received %+v", apAction.ID, rcv)
+ }
+
+ actESP := &actExport{
+ aCfg: apAction,
+ }
+ if rcv := actESP.id(); rcv != apAction.ID {
+ t.Errorf("Expected %+v, received %+v", apAction.ID, rcv)
+ }
+}
diff --git a/actions/log_test.go b/actions/log_test.go
new file mode 100644
index 000000000..d0d3a0abd
--- /dev/null
+++ b/actions/log_test.go
@@ -0,0 +1,110 @@
+/*
+Real-time Online/Offline Charging System (OerS) 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 actions
+
+import (
+ "reflect"
+ "testing"
+ "time"
+
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestACExecuteActCDRLog(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ cfg.ActionSCfg().CDRsConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCDRs)}
+ cfg.TemplatesCfg()[utils.MetaCdrLog][0].Filters = []string{"invalid_filter_value"}
+ data := engine.NewInternalDB(nil, nil, true)
+ dm := engine.NewDataManager(data, cfg.CacheCfg(), nil)
+ fltr := engine.NewFilterS(cfg, nil, dm)
+ apAction := &engine.APAction{
+ ID: "TEST_ACTION",
+ Type: utils.CDRLog,
+ }
+
+ dataStorage := utils.MapStorage{
+ utils.MetaReq: map[string]interface{}{
+ utils.AccountField: "1001",
+ },
+ utils.MetaOpts: map[string]interface{}{
+ utils.Usage: 10 * time.Minute,
+ },
+ }
+
+ actCdrLG := &actCDRLog{
+ config: cfg,
+ filterS: fltr,
+ aCfg: apAction,
+ }
+ expected := "NOT_FOUND:invalid_filter_value"
+ if err := actCdrLG.execute(nil, dataStorage,
+ utils.EmptyString); err == nil || err.Error() != expected {
+ t.Errorf("Expected %+v, received %+v", expected, err)
+ }
+}
+
+func TestACActLogger(t *testing.T) {
+ actLog := &actLog{
+ aCfg: &engine.APAction{
+ ID: "TEST_ACTION",
+ Type: utils.CDRLog,
+ },
+ }
+ if rcv := actLog.id(); rcv != "TEST_ACTION" {
+ t.Errorf("Expected %+v, received %+v", "TEST_ACTION", rcv)
+ }
+ if rcv := actLog.cfg(); !reflect.DeepEqual(rcv, actLog.aCfg) {
+ t.Errorf("Expected %+v, received %+v", utils.ToJSON(actLog.aCfg), utils.ToJSON(rcv))
+ }
+}
+
+func TestACResetStatsAndThresholds(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ apAction := &engine.APAction{
+ ID: "TEST_ACTION",
+ Type: utils.CDRLog,
+ }
+ actResStats := &actResetStat{
+ tnt: "cgrates.org",
+ config: cfg,
+ aCfg: apAction,
+ }
+
+ if rcv := actResStats.id(); rcv != "TEST_ACTION" {
+ t.Errorf("Expected %+v, received %+v", "TEST_ACTION", rcv)
+ }
+ if rcv := actResStats.cfg(); !reflect.DeepEqual(rcv, actResStats.aCfg) {
+ t.Errorf("Expected %+v, received %+v", utils.ToJSON(actResStats.aCfg), utils.ToJSON(rcv))
+ }
+
+ actResTh := &actResetThreshold{
+ tnt: "cgrates.org",
+ config: cfg,
+ aCfg: apAction,
+ }
+
+ if rcv := actResTh.id(); rcv != "TEST_ACTION" {
+ t.Errorf("Expected %+v, received %+v", "TEST_ACTION", rcv)
+ }
+ if rcv := actResTh.cfg(); !reflect.DeepEqual(rcv, actResTh.aCfg) {
+ t.Errorf("Expected %+v, received %+v", utils.ToJSON(actResTh.aCfg), utils.ToJSON(rcv))
+ }
+}