diff --git a/sessions/sessionscover_it_test.go b/sessions/sessionscover_it_test.go
index 21554ea8e..253ff422c 100644
--- a/sessions/sessionscover_it_test.go
+++ b/sessions/sessionscover_it_test.go
@@ -1 +1,286 @@
+/*
+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 sessions
+
+import (
+ "bytes"
+ "io/ioutil"
+ "log"
+ "os"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/cgrates/cgrates/config"
+ "github.com/cgrates/cgrates/engine"
+ "github.com/cgrates/cgrates/utils"
+)
+
+var (
+ sTests = []func(t *testing.T){
+ /*
+ testSetSTerminator,
+ testSetSTerminatorError,
+ testSetSTerminatorAutomaticTermination,
+ testSetSTerminatorManualTermination,
+
+ */
+ testForceSTerminatorManualTermination,
+ }
+)
+
+func TestSessionsIT(t *testing.T) {
+ for _, test := range sTests {
+ log.SetOutput(ioutil.Discard)
+ t.Run("Runing Sessions tests", test)
+ }
+}
+
+func testSetSTerminator(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ cfg.SessionSCfg().SessionTTL = time.Second
+ data := engine.NewInternalDB(nil, nil, true)
+ dm := engine.NewDataManager(data, cfg.CacheCfg(), nil)
+ sessions := NewSessionS(cfg, dm, nil)
+
+ ss := new(Session)
+
+ opts := engine.MapEvent{
+ utils.OptsDebitInterval: "0s",
+ }
+
+ terminator := &sTerminator{
+ ttl: cfg.SessionSCfg().SessionTTL,
+ }
+ sessions.setSTerminator(ss, opts)
+ ss.sTerminator.timer = nil
+ ss.sTerminator.endChan = nil
+ if !reflect.DeepEqual(terminator, ss.sTerminator) {
+ t.Errorf("Expected %+v, received %+v", terminator, ss.sTerminator)
+ }
+
+ opts = engine.MapEvent{
+ utils.OptsSessionTTL: "1s",
+ utils.OptsSessionTTLMaxDelay: "1s",
+ utils.OptsSessionTTLLastUsed: "2s",
+ utils.OptsSessionTTLLastUsage: "0s",
+ utils.OptsSessionTTLUsage: "5s",
+ }
+ ss.sTerminator = &sTerminator{
+ timer: time.NewTimer(cfg.SessionSCfg().SessionTTL),
+ }
+
+ terminator = &sTerminator{
+ ttl: 0,
+ ttlLastUsed: utils.DurationPointer(2 * time.Second),
+ ttlUsage: utils.DurationPointer(5 * time.Second),
+ ttlLastUsage: utils.DurationPointer(0),
+ }
+ sessions.setSTerminator(ss, opts)
+ ss.sTerminator.timer = nil
+ ss.sTerminator.endChan = nil
+ ss.sTerminator.ttl = 0
+ if !reflect.DeepEqual(terminator, ss.sTerminator) {
+ t.Errorf("Expected %+v, received %+v", terminator, ss.sTerminator)
+ }
+
+ ss.OptsStart = engine.MapEvent{
+ utils.OptsSessionTTL: "1s",
+ utils.OptsSessionTTLMaxDelay: "1s",
+ utils.OptsSessionTTLLastUsed: "2s",
+ utils.OptsSessionTTLLastUsage: "0s",
+ utils.OptsSessionTTLUsage: "5s",
+ }
+ ss.sTerminator = &sTerminator{
+ timer: time.NewTimer(cfg.SessionSCfg().SessionTTL),
+ }
+ opts = engine.MapEvent{}
+ sessions.setSTerminator(ss, opts)
+ ss.sTerminator.timer = nil
+ ss.sTerminator.endChan = nil
+ ss.sTerminator.ttl = 0
+ if !reflect.DeepEqual(terminator, ss.sTerminator) {
+ t.Errorf("Expected %+v, received %+v", terminator, ss.sTerminator)
+ }
+}
+
+func testSetSTerminatorError(t *testing.T) {
+ cfg := config.NewDefaultCGRConfig()
+ cfg.SessionSCfg().SessionTTL = time.Second
+ data := engine.NewInternalDB(nil, nil, true)
+ dm := engine.NewDataManager(data, cfg.CacheCfg(), nil)
+ sessions := NewSessionS(cfg, dm, nil)
+
+ ss := &Session{}
+
+ 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)
+
+ //Cannot set a terminate when ttl is 0
+ ss.OptsStart = engine.MapEvent{
+ utils.OptsSessionTTL: "0s",
+ }
+ opts := engine.MapEvent{}
+ sessions.setSTerminator(ss, opts)
+
+ //Invalid format types for time duration
+ ss.OptsStart = engine.MapEvent{
+ utils.OptsSessionTTL: "invalid_time_format",
+ }
+ sessions.setSTerminator(ss, opts)
+ expected := "cannot extract <*sessionTTL> for session:<>, from it's options: <{}>, err: "
+ if rcv := buff.String(); !strings.Contains(rcv, expected) {
+ t.Errorf("Expected %+v, received %+v", expected, rcv)
+ }
+
+ buff = new(bytes.Buffer)
+ log.SetOutput(buff)
+
+ ss.OptsStart = engine.MapEvent{
+ utils.OptsSessionTTL: "1s",
+ utils.OptsSessionTTLMaxDelay: "invalid_time_format",
+ }
+ sessions.setSTerminator(ss, opts)
+ expected = "cannot extract <*sessionTTLMaxDelay> for session:<>, from it's options: <{}>, err: "
+ if rcv := buff.String(); !strings.Contains(rcv, expected) {
+ t.Errorf("Expected %+v, received %+v", expected, rcv)
+ }
+
+ buff = new(bytes.Buffer)
+ log.SetOutput(buff)
+
+ ss.OptsStart = engine.MapEvent{
+ utils.OptsSessionTTL: "1s",
+ utils.OptsSessionTTLMaxDelay: "2s",
+ utils.OptsSessionTTLLastUsed: "invalid_time_format",
+ }
+ sessions.setSTerminator(ss, opts)
+ expected = "cannot extract <*sessionTTLLastUsed> for session:<>, from it's options: <{}>, err: "
+ if rcv := buff.String(); !strings.Contains(rcv, expected) {
+ t.Errorf("Expected %+v, received %+v", expected, rcv)
+ }
+
+ buff = new(bytes.Buffer)
+ log.SetOutput(buff)
+
+ ss.OptsStart = engine.MapEvent{
+ utils.OptsSessionTTL: "1s",
+ utils.OptsSessionTTLMaxDelay: "2s",
+ utils.OptsSessionTTLLastUsed: "1s",
+ utils.OptsSessionTTLLastUsage: "invalid_time_format",
+ }
+ sessions.setSTerminator(ss, opts)
+ expected = "cannot extract <*sessionTTLLastUsage> for session:<>, from it's options: <{}>, err: "
+ if rcv := buff.String(); !strings.Contains(rcv, expected) {
+ t.Errorf("Expected %+v, received %+v", expected, rcv)
+ }
+
+ buff = new(bytes.Buffer)
+ log.SetOutput(buff)
+
+ cfg.SessionSCfg().SessionTTLMaxDelay = utils.DurationPointer(time.Second)
+ sessions = NewSessionS(cfg, dm, nil)
+ ss.OptsStart = engine.MapEvent{
+ utils.OptsSessionTTLLastUsed: "1s",
+ utils.OptsSessionTTLLastUsage: "5s",
+ utils.OptsSessionTTLUsage: "invalid_time_format",
+ }
+ sessions.setSTerminator(ss, opts)
+ expected = "cannot extract <*sessionTTLUsage> for session:<>, from it's options: <{}>, err: "
+ if rcv := buff.String(); !strings.Contains(rcv, expected) {
+ t.Errorf("Expected %+v, received %+v", expected, rcv)
+ }
+
+ log.SetOutput(os.Stderr)
+}
+
+func testSetSTerminatorAutomaticTermination(t *testing.T) {
+ ss := &Session{}
+
+ cfg := config.NewDefaultCGRConfig()
+ data := engine.NewInternalDB(nil, nil, true)
+ dm := engine.NewDataManager(data, cfg.CacheCfg(), nil)
+ sessions := NewSessionS(cfg, dm, nil)
+
+ opts := engine.MapEvent{
+ utils.OptsSessionTTL: "1s",
+ utils.OptsSessionTTLLastUsage: "0s",
+ }
+
+ sessions.setSTerminator(ss, opts)
+ select {
+ case <-time.After(3 * time.Second):
+ t.Fatal("timeout")
+ case <-ss.sTerminator.endChan:
+ }
+}
+
+func testSetSTerminatorManualTermination(t *testing.T) {
+ ss := &Session{}
+
+ cfg := config.NewDefaultCGRConfig()
+ data := engine.NewInternalDB(nil, nil, true)
+ dm := engine.NewDataManager(data, cfg.CacheCfg(), nil)
+ sessions := NewSessionS(cfg, dm, nil)
+
+ opts := engine.MapEvent{
+ utils.OptsSessionTTL: "1s",
+ }
+
+ sessions.setSTerminator(ss, opts)
+ ss.sTerminator.endChan <- struct{}{}
+}
+
+func testForceSTerminatorManualTermination(t *testing.T) {
+ ss := &Session{
+ CGRID: "CGRID",
+ Tenant: "cgrates.org",
+ ResourceID: "resourceID",
+ ClientConnID: "ClientConnID",
+ EventStart: engine.NewMapEvent(nil),
+ DebitInterval: 18,
+ SRuns: []*SRun{
+ {Event: engine.NewMapEvent(nil),
+ CD: &engine.CallDescriptor{Category: "test"},
+ EventCost: &engine.EventCost{CGRID: "testCGRID"},
+ ExtraDuration: 1,
+ LastUsage: 2,
+ TotalUsage: 3,
+ NextAutoDebit: utils.TimePointer(time.Date(2020, time.April, 18, 23, 0, 0, 0, time.UTC)),
+ },
+ },
+ }
+
+ cfg := config.NewDefaultCGRConfig()
+ data := engine.NewInternalDB(nil, nil, true)
+ dm := engine.NewDataManager(data, cfg.CacheCfg(), nil)
+ sessions := NewSessionS(cfg, dm, nil)
+
+ expected := "MANDATORY_IE_MISSING: [connIDs]"
+ if err := sessions.forceSTerminate(ss, time.Second, nil, nil); err == nil || err.Error() != expected {
+ t.Errorf("Expected %+v, receive %+v", expected, err)
+ }
+}