diff --git a/agents/asterisk_event.go b/agents/asterisk_event.go index c2d4ea221..da0989e82 100644 --- a/agents/asterisk_event.go +++ b/agents/asterisk_event.go @@ -21,6 +21,7 @@ package agents import ( "strings" + "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/sessions" "github.com/cgrates/cgrates/utils" ) @@ -174,7 +175,37 @@ func (smaEv *SMAsteriskEvent) ExtraParameters() (extraParams map[string]string) return } -func (smaEv *SMAsteriskEvent) AsSMGenericEvent() *sessions.SMGenericEvent { +func (smaEv *SMAsteriskEvent) UpdateCGREvent(cgrEv *utils.CGREvent) error { + resCGREv := *cgrEv + switch smaEv.EventType() { + case ARIChannelStateChange: + resCGREv.Event[utils.EVENT_NAME] = SMASessionStart + resCGREv.Event[utils.AnswerTime] = smaEv.Timestamp() + case ARIChannelDestroyed: + resCGREv.Event[utils.EVENT_NAME] = SMASessionTerminate + resCGREv.Event[utils.DISCONNECT_CAUSE] = smaEv.DisconnectCause() + if _, hasIt := resCGREv.Event[utils.AnswerTime]; !hasIt { + resCGREv.Event[utils.Usage] = "0s" + } else { + if aTime, err := utils.IfaceAsTime(resCGREv.Event[utils.AnswerTime], config.CgrConfig().DefaultTimezone); err != nil { + return err + } else if aTime.IsZero() { + resCGREv.Event[utils.Usage] = "0s" + } else { + actualTime, err := utils.ParseTimeDetectLayout(smaEv.Timestamp(), "") + if err != nil { + return err + } + resCGREv.Event[utils.Usage] = actualTime.Sub(aTime).String() + } + } + } + *cgrEv = resCGREv + return nil +} + +func (smaEv *SMAsteriskEvent) AsMapStringInterface() (mp map[string]interface{}) { + mp = make(map[string]interface{}) var evName string switch smaEv.EventType() { case ARIStasisStart: @@ -184,62 +215,144 @@ func (smaEv *SMAsteriskEvent) AsSMGenericEvent() *sessions.SMGenericEvent { case ARIChannelDestroyed: evName = SMASessionTerminate } - smgEv := sessions.SMGenericEvent{utils.EVENT_NAME: evName} - smgEv[utils.OriginID] = smaEv.ChannelID() + mp[utils.EVENT_NAME] = evName + mp[utils.OriginID] = smaEv.ChannelID() if smaEv.RequestType() != "" { - smgEv[utils.RequestType] = smaEv.RequestType() + mp[utils.RequestType] = smaEv.RequestType() } if smaEv.Tenant() != "" { - smgEv[utils.Tenant] = smaEv.Tenant() + mp[utils.Tenant] = smaEv.Tenant() } if smaEv.Category() != "" { - smgEv[utils.Category] = smaEv.Category() + mp[utils.Category] = smaEv.Category() } if smaEv.Subject() != "" { - smgEv[utils.Subject] = smaEv.Subject() + mp[utils.Subject] = smaEv.Subject() } - smgEv[utils.OriginHost] = smaEv.OriginatorIP() - smgEv[utils.Account] = smaEv.Account() - smgEv[utils.Destination] = smaEv.Destination() - smgEv[utils.SetupTime] = smaEv.Timestamp() + mp[utils.OriginHost] = smaEv.OriginatorIP() + mp[utils.Account] = smaEv.Account() + mp[utils.Destination] = smaEv.Destination() + mp[utils.SetupTime] = smaEv.SetupTime() if smaEv.Supplier() != "" { - smgEv[utils.SUPPLIER] = smaEv.Supplier() + mp[utils.SUPPLIER] = smaEv.Supplier() } for extraKey, extraVal := range smaEv.ExtraParameters() { // Append extraParameters - smgEv[extraKey] = extraVal + mp[extraKey] = extraVal } - return &smgEv + return } -// Updates fields in smgEv based on own fields -// Using pointer so we update it directly in cache -func (smaEv *SMAsteriskEvent) UpdateSMGEvent(smgEv *sessions.SMGenericEvent) error { - resSMGEv := *smgEv - switch smaEv.EventType() { - case ARIChannelStateChange: - if smaEv.ChannelState() == channelUp { - resSMGEv[utils.EVENT_NAME] = SMASessionStart - resSMGEv[utils.AnswerTime] = smaEv.Timestamp() +// AsCDR converts KamEvent into CGREvent +func (smaEv *SMAsteriskEvent) AsCGREvent(timezone string) (cgrEv *utils.CGREvent, err error) { + setupTime, err := utils.ParseTimeDetectLayout( + smaEv.Timestamp(), timezone) + if err != nil { + return + } + cgrEv = &utils.CGREvent{ + Tenant: utils.FirstNonEmpty(smaEv.Tenant(), + config.CgrConfig().DefaultTenant), + ID: utils.UUIDSha1Prefix(), + Time: &setupTime, + Event: smaEv.AsMapStringInterface(), + } + return cgrEv, nil +} + +func (smaEv *SMAsteriskEvent) V1AuthorizeArgs() (args *sessions.V1AuthorizeArgs) { + cgrEv, err := smaEv.AsCGREvent(config.CgrConfig().DefaultTimezone) + if err != nil { + return + } + args = &sessions.V1AuthorizeArgs{ + GetMaxUsage: true, + CGREvent: *cgrEv, + } + // For the moment hardcoded only GetMaxUsage : true + /* + subsystems, has := kev[KamCGRSubsystems] + if !has { + return } - case ARIChannelDestroyed: - resSMGEv[utils.EVENT_NAME] = SMASessionTerminate - resSMGEv[utils.DISCONNECT_CAUSE] = smaEv.DisconnectCause() - if _, hasIt := resSMGEv[utils.AnswerTime]; !hasIt { - resSMGEv[utils.Usage] = "0s" - } else { - if aTime, err := smgEv.GetAnswerTime(utils.META_DEFAULT, ""); err != nil { - return err - } else if aTime.IsZero() { - resSMGEv[utils.Usage] = "0s" - } else { - actualTime, err := utils.ParseTimeDetectLayout(smaEv.Timestamp(), "") - if err != nil { - return err - } - resSMGEv[utils.Usage] = actualTime.Sub(aTime).String() + if strings.Index(subsystems, utils.MetaAccounts) == -1 { + args.GetMaxUsage = false + } + if strings.Index(subsystems, utils.MetaResources) != -1 { + args.AuthorizeResources = true + } + if strings.Index(subsystems, utils.MetaSuppliers) != -1 { + args.GetSuppliers = true + if strings.Index(subsystems, utils.MetaSuppliersEventCost) != -1 { + args.SuppliersMaxCost = utils.MetaEventCost + } + if strings.Index(subsystems, utils.MetaSuppliersIgnoreErrors) != -1 { + args.SuppliersIgnoreErrors = true } } - } - *smgEv = resSMGEv - return nil + if strings.Index(subsystems, utils.MetaAttributes) != -1 { + args.GetAttributes = true + } + if strings.Index(subsystems, utils.MetaThresholds) != -1 { + args.ProcessThresholds = utils.BoolPointer(true) + } + if strings.Index(subsystems, utils.MetaStats) != -1 { + args.ProcessStatQueues = utils.BoolPointer(true) + } + */ + return +} + +func (smaEv *SMAsteriskEvent) V1InitSessionArgs(cgrEv utils.CGREvent) (args *sessions.V1InitSessionArgs) { + args = &sessions.V1InitSessionArgs{ // defaults + InitSession: true, + CGREvent: cgrEv, + } + /* + subsystems, has := kev[KamCGRSubsystems] + if !has { + return + } + if strings.Index(subsystems, utils.MetaAccounts) == -1 { + args.InitSession = false + } + if strings.Index(subsystems, utils.MetaResources) != -1 { + args.AllocateResources = true + } + if strings.Index(subsystems, utils.MetaAttributes) != -1 { + args.GetAttributes = true + } + if strings.Index(subsystems, utils.MetaThresholds) != -1 { + args.ProcessThresholds = utils.BoolPointer(true) + } + if strings.Index(subsystems, utils.MetaStats) != -1 { + args.ProcessStatQueues = utils.BoolPointer(true) + } + */ + return +} + +func (smaEv *SMAsteriskEvent) V1TerminateSessionArgs(cgrEv utils.CGREvent) (args *sessions.V1TerminateSessionArgs) { + args = &sessions.V1TerminateSessionArgs{ // defaults + TerminateSession: true, + CGREvent: cgrEv, + } + /* + subsystems, has := kev[KamCGRSubsystems] + if !has { + return + } + if strings.Index(subsystems, utils.MetaAccounts) == -1 { + args.TerminateSession = false + } + if strings.Index(subsystems, utils.MetaResources) != -1 { + args.ReleaseResources = true + } + if strings.Index(subsystems, utils.MetaThresholds) != -1 { + args.ProcessThresholds = utils.BoolPointer(true) + } + if strings.Index(subsystems, utils.MetaStats) != -1 { + args.ProcessStatQueues = utils.BoolPointer(true) + } + */ + return } diff --git a/agents/asterisk_event_test.go b/agents/asterisk_event_test.go index ef12a07e3..ba31b3ae6 100644 --- a/agents/asterisk_event_test.go +++ b/agents/asterisk_event_test.go @@ -21,9 +21,6 @@ import ( "encoding/json" "reflect" "testing" - - "github.com/cgrates/cgrates/sessions" - "github.com/cgrates/cgrates/utils" ) var ( @@ -328,212 +325,3 @@ func TestSMAEventExtraParameters(t *testing.T) { t.Errorf("Expecting: %+v, received: %+v", expExtraParams, extraParams) } } - -/* -func TestSMAEventUpdateFromEvent(t *testing.T) { - var ev map[string]interface{} - if err := json.Unmarshal([]byte(stasisStart), &ev); err != nil { - t.Error(err) - } - smaEv := NewSMAsteriskEvent(ev, "127.0.0.1") - ev = make(map[string]interface{}) - if err := json.Unmarshal([]byte(channelAnsweredDestroyed), &ev); err != nil { - t.Error(err) - } - smaEv2 := NewSMAsteriskEvent(ev, "127.0.0.1") - smaEv.UpdateFromEvent(smaEv2) - eSMAEv := &SMAsteriskEvent{ - ariEv: map[string]interface{}{ - "type": "ChannelDestroyed", - "args": []interface{}{"cgr_reqtype=*prepaid", "cgr_destination=1003", "extra1=val1", "extra2=val2"}, - "timestamp": "2016-09-12T13:54:27.335+0200", - "application": "cgrates_auth", - "cause_txt": "Normal Clearing", - "channel": map[string]interface{}{ - "id": "1473681228.6", - "state": "Up", - "name": "PJSIP/1001-00000004", - "caller": map[string]interface{}{ - "name": "1001", - "number": "1001"}, - "language": "en", - "connected": map[string]interface{}{ - "name": "", - "number": "1002"}, - "accountcode": "", - "dialplan": map[string]interface{}{ - "context": "internal", - "exten": "1002", - "priority": 3.0}, - "creationtime": "2016-09-12T13:53:48.918+0200"}, - "cause": 16.0}, - asteriskIP: "127.0.0.1", - cachedFields: map[string]string{"cgr_reqtype": "*prepaid", - "cgr_destination": "1003", "extra1": "val1", "extra2": "val2"}, - } - if !reflect.DeepEqual(eSMAEv, smaEv) { - t.Errorf("Expecting: %+v, received: %+v", eSMAEv, smaEv) - } -} -*/ - -//Here -func TestSMAEventAsSMGenericEvent(t *testing.T) { - var ev map[string]interface{} - if err := json.Unmarshal([]byte(stasisStart), &ev); err != nil { - t.Error(err) - } - eSMGEv := &sessions.SMGenericEvent{ - utils.EVENT_NAME: SMAAuthorization, - utils.OriginID: "1473681228.6", - utils.RequestType: "*prepaid", - utils.OriginHost: "127.0.0.1", - utils.Account: "1001", - utils.Destination: "1002", - utils.SetupTime: "2016-09-12T13:53:48.919+0200", - utils.SUPPLIER: "supplier1", - "extra1": "val1", - "extra2": "val2", - } - smaEv := NewSMAsteriskEvent(ev, "127.0.0.1") - if smgEv := smaEv.AsSMGenericEvent(); !reflect.DeepEqual(eSMGEv, smgEv) { - t.Errorf("Expecting: %+v, received: %+v", eSMGEv, smgEv) - } -} - -func TestSMAEventUpdateSMGEventAnswered(t *testing.T) { - var ev map[string]interface{} - if err := json.Unmarshal([]byte(channelStateChange), &ev); err != nil { - t.Error(err) - } - smaEv := NewSMAsteriskEvent(ev, "127.0.0.1") - smgEv := &sessions.SMGenericEvent{ - utils.EVENT_NAME: SMAAuthorization, - utils.OriginID: "1473681228.6", - utils.RequestType: "*prepaid", - utils.OriginHost: "127.0.0.1", - utils.Account: "1001", - utils.Destination: "1003", - utils.SetupTime: "2016-09-12T13:53:48.919+0200", - "extra1": "val1", - "extra2": "val2", - } - eSMGEv := &sessions.SMGenericEvent{ - utils.EVENT_NAME: SMASessionStart, - utils.OriginID: "1473681228.6", - utils.RequestType: "*prepaid", - utils.OriginHost: "127.0.0.1", - utils.Account: "1001", - utils.Destination: "1003", - utils.SetupTime: "2016-09-12T13:53:48.919+0200", - utils.AnswerTime: "2016-09-12T13:53:52.110+0200", - "extra1": "val1", - "extra2": "val2", - } - if err := smaEv.UpdateSMGEvent(smgEv); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eSMGEv, smgEv) { - t.Errorf("Expecting: %+v, received: %+v", eSMGEv, smgEv) - } - // Apply update using a terminate event - ev = make(map[string]interface{}) - if err = json.Unmarshal([]byte(channelAnsweredDestroyed), &ev); err != nil { - t.Error(err) - } - smaEv = NewSMAsteriskEvent(ev, "127.0.0.1") - eSMGEv = &sessions.SMGenericEvent{ - utils.EVENT_NAME: SMASessionTerminate, - utils.OriginID: "1473681228.6", - utils.RequestType: "*prepaid", - utils.OriginHost: "127.0.0.1", - utils.Account: "1001", - utils.Destination: "1003", - utils.SetupTime: "2016-09-12T13:53:48.919+0200", - utils.AnswerTime: "2016-09-12T13:53:52.110+0200", - utils.Usage: "35.225s", - utils.DISCONNECT_CAUSE: "Normal Clearing", - "extra1": "val1", - "extra2": "val2", - } - if err := smaEv.UpdateSMGEvent(smgEv); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eSMGEv, smgEv) { - t.Errorf("Expecting: %+v, received: %+v", eSMGEv, smgEv) - } -} - -func TestSMAEventUpdateSMGEventUnaswered(t *testing.T) { - smgEv := &sessions.SMGenericEvent{ - utils.EVENT_NAME: SMAAuthorization, - utils.OriginID: "1473681228.6", - utils.RequestType: "*prepaid", - utils.OriginHost: "127.0.0.1", - utils.Account: "1001", - utils.Destination: "1003", - utils.SetupTime: "2016-09-12T13:53:48.919+0200", - "extra1": "val1", - "extra2": "val2", - } - eSMGEv := &sessions.SMGenericEvent{ - utils.EVENT_NAME: SMASessionTerminate, - utils.OriginID: "1473681228.6", - utils.RequestType: "*prepaid", - utils.OriginHost: "127.0.0.1", - utils.Account: "1001", - utils.Destination: "1003", - utils.SetupTime: "2016-09-12T13:53:48.919+0200", - utils.Usage: "0s", - utils.DISCONNECT_CAUSE: "Normal Clearing", - "extra1": "val1", - "extra2": "val2", - } - // Apply update using a terminate event - ev := make(map[string]interface{}) - if err := json.Unmarshal([]byte(channelUnansweredDestroyed), &ev); err != nil { - t.Error(err) - } - smaEv := NewSMAsteriskEvent(ev, "127.0.0.1") - if err := smaEv.UpdateSMGEvent(smgEv); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eSMGEv, smgEv) { - t.Errorf("Expecting: %+v, received: %+v", eSMGEv, smgEv) - } -} - -func TestSMAEventUpdateSMGEventBusy(t *testing.T) { - smgEv := &sessions.SMGenericEvent{ - utils.EVENT_NAME: SMAAuthorization, - utils.OriginID: "1473681228.6", - utils.RequestType: "*prepaid", - utils.OriginHost: "127.0.0.1", - utils.Account: "1001", - utils.Destination: "1003", - utils.SetupTime: "2016-09-12T13:53:48.919+0200", - "extra1": "val1", - "extra2": "val2", - } - eSMGEv := &sessions.SMGenericEvent{ - utils.EVENT_NAME: SMASessionTerminate, - utils.OriginID: "1473681228.6", - utils.RequestType: "*prepaid", - utils.OriginHost: "127.0.0.1", - utils.Account: "1001", - utils.Destination: "1003", - utils.SetupTime: "2016-09-12T13:53:48.919+0200", - utils.Usage: "0s", - utils.DISCONNECT_CAUSE: "User busy", - "extra1": "val1", - "extra2": "val2", - } - // Apply update using a terminate event - ev := make(map[string]interface{}) - if err := json.Unmarshal([]byte(channelBusyDestroyed), &ev); err != nil { - t.Error(err) - } - smaEv := NewSMAsteriskEvent(ev, "127.0.0.1") - if err := smaEv.UpdateSMGEvent(smgEv); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eSMGEv, smgEv) { - t.Errorf("Expecting: %+v, received: %+v", eSMGEv, smgEv) - } -} diff --git a/agents/asteriskagent.go b/agents/asteriskagent.go index 5ece52e6c..1d6dc0c22 100644 --- a/agents/asteriskagent.go +++ b/agents/asteriskagent.go @@ -48,30 +48,33 @@ const ( SMASessionTerminate = "SMA_SESSION_TERMINATE" ) -func NewSMAsterisk(cgrCfg *config.CGRConfig, astConnIdx int, smgConn *utils.BiRPCInternalClient) (*SMAsterisk, error) { - sma := &SMAsterisk{cgrCfg: cgrCfg, smg: smgConn, - eventsCache: make(map[string]*sessions.SMGenericEvent)} +func NewAsteriskAgent(cgrCfg *config.CGRConfig, astConnIdx int, + smgConn *utils.BiRPCInternalClient) (*AsteriskAgent, error) { + sma := &AsteriskAgent{cgrCfg: cgrCfg, smg: smgConn, + eventsCache: make(map[string]*utils.CGREvent)} sma.smg.SetClientConn(sma) // pass the connection to SMA back into smg so we can receive the disconnects return sma, nil } -type SMAsterisk struct { +type AsteriskAgent struct { cgrCfg *config.CGRConfig // Separate from smCfg since there can be multiple astConnIdx int smg *utils.BiRPCInternalClient astConn *aringo.ARInGO astEvChan chan map[string]interface{} astErrChan chan error - eventsCache map[string]*sessions.SMGenericEvent // used to gather information about events during various phases - evCacheMux sync.RWMutex // Protect eventsCache + eventsCache map[string]*utils.CGREvent // used to gather information about events during various phases + evCacheMux sync.RWMutex // Protect eventsCache } -func (sma *SMAsterisk) connectAsterisk() (err error) { +func (sma *AsteriskAgent) connectAsterisk() (err error) { connCfg := sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx] sma.astEvChan = make(chan map[string]interface{}) sma.astErrChan = make(chan error) - sma.astConn, err = aringo.NewARInGO(fmt.Sprintf("ws://%s/ari/events?api_key=%s:%s&app=%s", connCfg.Address, connCfg.User, connCfg.Password, CGRAuthAPP), "http://cgrates.org", - connCfg.User, connCfg.Password, fmt.Sprintf("%s %s", utils.CGRateS, utils.VERSION), sma.astEvChan, sma.astErrChan, connCfg.ConnectAttempts, connCfg.Reconnects) + sma.astConn, err = aringo.NewARInGO(fmt.Sprintf("ws://%s/ari/events?api_key=%s:%s&app=%s", + connCfg.Address, connCfg.User, connCfg.Password, CGRAuthAPP), "http://cgrates.org", + connCfg.User, connCfg.Password, fmt.Sprintf("%s %s", utils.CGRateS, utils.VERSION), + sma.astEvChan, sma.astErrChan, connCfg.ConnectAttempts, connCfg.Reconnects) if err != nil { return err } @@ -79,7 +82,7 @@ func (sma *SMAsterisk) connectAsterisk() (err error) { } // Called to start the service -func (sma *SMAsterisk) ListenAndServe() (err error) { +func (sma *AsteriskAgent) ListenAndServe() (err error) { if err := sma.connectAsterisk(); err != nil { return err } @@ -88,7 +91,8 @@ func (sma *SMAsterisk) ListenAndServe() (err error) { case err = <-sma.astErrChan: return case astRawEv := <-sma.astEvChan: - smAsteriskEvent := NewSMAsteriskEvent(astRawEv, strings.Split(sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, ":")[0]) + smAsteriskEvent := NewSMAsteriskEvent(astRawEv, + strings.Split(sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, ":")[0]) switch smAsteriskEvent.EventType() { case ARIStasisStart: go sma.handleStasisStart(smAsteriskEvent) @@ -99,52 +103,69 @@ func (sma *SMAsterisk) ListenAndServe() (err error) { } } } - panic(" ListenAndServe out of select") + panic(" ListenAndServe out of select") } // hangupChannel will disconnect from CGRateS side with congestion reason -func (sma *SMAsterisk) hangupChannel(channelID string) (err error) { +func (sma *AsteriskAgent) hangupChannel(channelID string) (err error) { _, err = sma.astConn.Call(aringo.HTTP_DELETE, fmt.Sprintf("http://%s/ari/channels/%s", sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, channelID), url.Values{"reason": {"congestion"}}) return } -func (sma *SMAsterisk) handleStasisStart(ev *SMAsteriskEvent) { +func (sma *AsteriskAgent) handleStasisStart(ev *SMAsteriskEvent) { // Subscribe for channel updates even after we leave Stasis - if _, err := sma.astConn.Call(aringo.HTTP_POST, fmt.Sprintf("http://%s/ari/applications/%s/subscription?eventSource=channel:%s", - sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, CGRAuthAPP, ev.ChannelID()), nil); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when subscribing to events for channelID: %s", err.Error(), ev.ChannelID())) + if _, err := sma.astConn.Call(aringo.HTTP_POST, + fmt.Sprintf("http://%s/ari/applications/%s/subscription?eventSource=channel:%s", + sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, + CGRAuthAPP, ev.ChannelID()), nil); err != nil { + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when subscribingto events for channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) // Since we got error, disconnect channel if err := sma.hangupChannel(ev.ChannelID()); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", err.Error(), ev.ChannelID())) + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } return } - // Query the SMG via RPC for maxUsage - var maxUsage float64 - smgEv := ev.AsSMGenericEvent() - if err := sma.smg.Call("SMGenericV1.GetMaxUsage", *smgEv, &maxUsage); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to authorize session for channelID: %s", err.Error(), ev.ChannelID())) + //authorize Session + authArgs := ev.V1AuthorizeArgs() + if authArgs == nil { + utils.Logger.Err(fmt.Sprintf("<%s> event: %s cannot generate auth session arguments", + utils.AsteriskAgent, ev.ChannelID())) + return + } + var authReply sessions.V1AuthorizeReply + if err := sma.smg.Call(utils.SessionSv1AuthorizeEvent, authArgs, &authReply); err != nil { + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to authorize session for channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) if err := sma.hangupChannel(ev.ChannelID()); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", err.Error(), ev.ChannelID())) + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } return } - if maxUsage == 0 { + if authReply.MaxUsage != nil && *authReply.MaxUsage == time.Duration(0) { if err := sma.hangupChannel(ev.ChannelID()); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", err.Error(), ev.ChannelID())) + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } return - } else if maxUsage != -1 { + } else if *authReply.MaxUsage != time.Duration(-1) { // Set absolute timeout for non-postpaid calls - if _, err := sma.astConn.Call(aringo.HTTP_POST, fmt.Sprintf("http://%s/ari/channels/%s/variable?variable=%s", // Asterisk having issue with variable terminating empty so harcoding param in url - sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, ev.ChannelID(), CGRMaxSessionTime), - url.Values{"value": {strconv.FormatFloat(maxUsage*1000, 'f', -1, 64)}}); err != nil { // Asterisk expects value in ms - utils.Logger.Err(fmt.Sprintf(" Error: %s when setting %s for channelID: %s", err.Error(), CGRMaxSessionTime, ev.ChannelID())) + if _, err := sma.astConn.Call(aringo.HTTP_POST, + fmt.Sprintf("http://%s/ari/channels/%s/variable?variable=%s&value=%d", // Asterisk having issue with variable terminating empty so harcoding param in url + sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, + ev.ChannelID(), CGRMaxSessionTime, int64(authReply.MaxUsage.Seconds()*1000)), + url.Values{"value": {strconv.FormatFloat( + authReply.MaxUsage.Seconds()*1000, 'f', -1, 64)}}); err != nil { // Asterisk expects value in ms + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when setting %s for channelID: %s", + utils.AsteriskAgent, err.Error(), CGRMaxSessionTime, ev.ChannelID())) // Since we got error, disconnect channel if err := sma.hangupChannel(ev.ChannelID()); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", err.Error(), ev.ChannelID())) + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } return } @@ -152,108 +173,133 @@ func (sma *SMAsterisk) handleStasisStart(ev *SMAsteriskEvent) { // Exit channel from stasis if _, err := sma.astConn.Call(aringo.HTTP_POST, fmt.Sprintf("http://%s/ari/channels/%s/continue", - sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, ev.ChannelID()), nil); err != nil { + sma.cgrCfg.AsteriskAgentCfg().AsteriskConns[sma.astConnIdx].Address, + ev.ChannelID()), nil); err != nil { } // Done with processing event, cache it for later use sma.evCacheMux.Lock() - sma.eventsCache[ev.ChannelID()] = smgEv + sma.eventsCache[ev.ChannelID()] = &authArgs.CGREvent sma.evCacheMux.Unlock() } // Ussually channelUP -func (sma *SMAsterisk) handleChannelStateChange(ev *SMAsteriskEvent) { +func (sma *AsteriskAgent) handleChannelStateChange(ev *SMAsteriskEvent) { if ev.ChannelState() != channelUp { return } sma.evCacheMux.RLock() - smgEv, hasIt := sma.eventsCache[ev.ChannelID()] + cgrEv, hasIt := sma.eventsCache[ev.ChannelID()] sma.evCacheMux.RUnlock() if !hasIt { // Not handled by us return } sma.evCacheMux.Lock() - err := ev.UpdateSMGEvent(smgEv) // Updates the event directly in the cache + err := ev.UpdateCGREvent(cgrEv) // Updates the event directly in the cache sma.evCacheMux.Unlock() if err != nil { utils.Logger.Err( - fmt.Sprintf(" Error: %s when attempting to initiate session for channelID: %s", - err.Error(), ev.ChannelID())) + fmt.Sprintf("<%s> Error: %s when attempting to initiate session for channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) if err := sma.hangupChannel(ev.ChannelID()); err != nil { utils.Logger.Err( - fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", - err.Error(), ev.ChannelID())) + fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } return } - var maxUsage time.Duration - if err := sma.smg.Call(utils.SMGenericV2InitiateSession, - *smgEv, &maxUsage); err != nil { + // populate init session args + initSessionArgs := ev.V1InitSessionArgs(*cgrEv) + if initSessionArgs == nil { + utils.Logger.Err(fmt.Sprintf("<%s> event: %s cannot generate init session arguments", + utils.AsteriskAgent, ev.ChannelID())) + return + } + + //initit Session + var initReply sessions.V1InitSessionReply + if err := sma.smg.Call(utils.SessionSv1InitiateSession, + initSessionArgs, &initReply); err != nil { utils.Logger.Err( - fmt.Sprintf(" Error: %s when attempting to initiate session for channelID: %s", - err.Error(), ev.ChannelID())) + fmt.Sprintf("<%s> Error: %s when attempting to initiate session for channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) if err := sma.hangupChannel(ev.ChannelID()); err != nil { utils.Logger.Err( - fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", - err.Error(), ev.ChannelID())) + fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } return - } else if maxUsage == 0 { + } else if initReply.MaxUsage != nil && *initReply.MaxUsage == time.Duration(0) { if err := sma.hangupChannel(ev.ChannelID()); err != nil { utils.Logger.Err( - fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", - err.Error(), ev.ChannelID())) + fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } return } + } // Channel disconnect -func (sma *SMAsterisk) handleChannelDestroyed(ev *SMAsteriskEvent) { +func (sma *AsteriskAgent) handleChannelDestroyed(ev *SMAsteriskEvent) { sma.evCacheMux.RLock() - smgEv, hasIt := sma.eventsCache[ev.ChannelID()] + cgrEv, hasIt := sma.eventsCache[ev.ChannelID()] sma.evCacheMux.RUnlock() if !hasIt { // Not handled by us return } sma.evCacheMux.Lock() - err := ev.UpdateSMGEvent(smgEv) // Updates the event directly in the cache + err := ev.UpdateCGREvent(cgrEv) // Updates the event directly in the cache sma.evCacheMux.Unlock() if err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to initiate session for channelID: %s", err.Error(), ev.ChannelID())) + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to initiate session for channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) if err := sma.hangupChannel(ev.ChannelID()); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", err.Error(), ev.ChannelID())) + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } return } + // populate terminate session args + tsArgs := ev.V1TerminateSessionArgs(*cgrEv) + if tsArgs == nil { + utils.Logger.Err(fmt.Sprintf("<%s> event: %s cannot generate terminate session arguments", + utils.AsteriskAgent, ev.ChannelID())) + return + } + var reply string - if err := sma.smg.Call("SMGenericV1.TerminateSession", *smgEv, &reply); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to terminate session for channelID: %s", err.Error(), ev.ChannelID())) + if err := sma.smg.Call(utils.SessionSv1TerminateSession, + tsArgs, &reply); err != nil { + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to terminate session for channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } if sma.cgrCfg.AsteriskAgentCfg().CreateCDR { - if err := sma.smg.Call("SMGenericV1.ProcessCDR", *smgEv, &reply); err != nil { - utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to process CDR for channelID: %s", err.Error(), ev.ChannelID())) + if err := sma.smg.Call(utils.SessionSv1ProcessCDR, *cgrEv, &reply); err != nil { + utils.Logger.Err(fmt.Sprintf("<%s> Error: %s when attempting to process CDR for channelID: %s", + utils.AsteriskAgent, err.Error(), ev.ChannelID())) } } + } // Called to shutdown the service -func (sma *SMAsterisk) ServiceShutdown() error { +func (sma *AsteriskAgent) ServiceShutdown() error { return nil } // Internal method to disconnect session in asterisk -func (sma *SMAsterisk) V1DisconnectSession(args utils.AttrDisconnectSession, reply *string) error { +func (sma *AsteriskAgent) V1DisconnectSession(args utils.AttrDisconnectSession, reply *string) error { channelID := sessions.SMGenericEvent(args.EventStart).GetOriginID(utils.META_DEFAULT) if err := sma.hangupChannel(channelID); err != nil { utils.Logger.Err( - fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", - err.Error(), channelID)) + fmt.Sprintf("<%s> Error: %s when attempting to disconnect channelID: %s", + utils.AsteriskAgent, err.Error(), channelID)) } *reply = utils.OK return nil } // rpcclient.RpcClientConnection interface -func (sma *SMAsterisk) Call(serviceMethod string, args interface{}, reply interface{}) error { +func (sma *AsteriskAgent) Call(serviceMethod string, args interface{}, reply interface{}) error { return utils.RPCCall(sma, serviceMethod, args, reply) } diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index a75dec9cc..1ebe22f02 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -241,7 +241,7 @@ func startAsteriskAgent(internalSMGChan chan rpcclient.RpcClientConnection, exit internalSMGChan <- smgRpcConn birpcClnt := utils.NewBiRPCInternalClient(smgRpcConn.(*sessions.SMGeneric)) for connIdx := range cfg.AsteriskAgentCfg().AsteriskConns { // Instantiate connections towards asterisk servers - sma, err := agents.NewSMAsterisk(cfg, connIdx, birpcClnt) + sma, err := agents.NewAsteriskAgent(cfg, connIdx, birpcClnt) if err != nil { utils.Logger.Err(fmt.Sprintf(" error: %s!", err)) exitChan <- true diff --git a/data/conf/samples/tutmongojson/cgrates.json b/data/conf/samples/tutmongojson/cgrates.json new file mode 100644 index 000000000..ba8106486 --- /dev/null +++ b/data/conf/samples/tutmongojson/cgrates.json @@ -0,0 +1,69 @@ +{ +// CGRateS Configuration file + + +"general": { + "log_level": 7, + "reply_timeout": "30s", + "dbdata_encoding": "json", +}, + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + + +"data_db": { + "db_type": "mongo", + "db_name": "10", + "db_port": 27017, +}, + + +"stor_db": { + "db_type": "mongo", + "db_port": 27017, +}, + + +"cache":{ + "destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "rating_plans": {"limit": 10000, "ttl":"0s","precache": true}, + "rating_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "lcr_rules": {"limit": 10000, "ttl":"0s", "precache": true}, + "cdr_stats": {"limit": 10000, "ttl":"0s", "precache": true}, + "actions": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "account_action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_triggers": {"limit": 10000, "ttl":"0s", "precache": true}, + "shared_groups": {"limit": 10000, "ttl":"0s", "precache": true}, + "aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "derived_chargers": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resources": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueues": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueue_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "thresholds": {"limit": 10000, "ttl":"0s", "precache": true}, + "threshold_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "filters": {"limit": 10000, "ttl":"0s", "precache": true}, + "supplier_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "attribute_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_filter_indexes" :{"limit": 10000, "ttl":"0s"}, + "resource_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_revindexes" :{"limit": 10000, "ttl":"0s"}, + "attribute_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "attribute_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, +}, + + +} \ No newline at end of file diff --git a/data/conf/samples/tutmongomsgpack/cgrates.json b/data/conf/samples/tutmongomsgpack/cgrates.json new file mode 100644 index 000000000..5200fd05e --- /dev/null +++ b/data/conf/samples/tutmongomsgpack/cgrates.json @@ -0,0 +1,69 @@ +{ +// CGRateS Configuration file + + +"general": { + "log_level": 7, + "reply_timeout": "30s", + "dbdata_encoding": "msgpack", +}, + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + + +"data_db": { + "db_type": "mongo", + "db_name": "11", + "db_port": 27017, +}, + + +"stor_db": { + "db_type": "mongo", + "db_port": 27017, +}, + + +"cache":{ + "destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "rating_plans": {"limit": 10000, "ttl":"0s","precache": true}, + "rating_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "lcr_rules": {"limit": 10000, "ttl":"0s", "precache": true}, + "cdr_stats": {"limit": 10000, "ttl":"0s", "precache": true}, + "actions": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "account_action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_triggers": {"limit": 10000, "ttl":"0s", "precache": true}, + "shared_groups": {"limit": 10000, "ttl":"0s", "precache": true}, + "aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "derived_chargers": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resources": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueues": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueue_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "thresholds": {"limit": 10000, "ttl":"0s", "precache": true}, + "threshold_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "filters": {"limit": 10000, "ttl":"0s", "precache": true}, + "supplier_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "attribute_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_filter_indexes" :{"limit": 10000, "ttl":"0s"}, + "resource_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_revindexes" :{"limit": 10000, "ttl":"0s"}, + "attribute_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "attribute_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, +}, + + +} \ No newline at end of file diff --git a/data/conf/samples/tutmysqljson/cgrates.json b/data/conf/samples/tutmysqljson/cgrates.json new file mode 100644 index 000000000..303bdf609 --- /dev/null +++ b/data/conf/samples/tutmysqljson/cgrates.json @@ -0,0 +1,67 @@ +{ +// CGRateS Configuration file +// + + +"general": { + "log_level": 7, + "dbdata_encoding": "json", // encoding used to store object data in strings: +}, + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + +"data_db": { // database used to store runtime data (eg: accounts, cdr stats) + "db_type": "redis", // data_db type: + "db_port": 6379, // data_db port to reach the database + "db_name": "10", // data_db database name to connect to + +}, + +"stor_db": { + "db_password": "CGRateS.org", +}, + + +"cache":{ + "destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "rating_plans": {"limit": 10000, "ttl":"0s","precache": true}, + "rating_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "lcr_rules": {"limit": 10000, "ttl":"0s", "precache": true}, + "cdr_stats": {"limit": 10000, "ttl":"0s", "precache": true}, + "actions": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "account_action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_triggers": {"limit": 10000, "ttl":"0s", "precache": true}, + "shared_groups": {"limit": 10000, "ttl":"0s", "precache": true}, + "aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "derived_chargers": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resources": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueues": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueue_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "thresholds": {"limit": 10000, "ttl":"0s", "precache": true}, + "threshold_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "filters": {"limit": 10000, "ttl":"0s", "precache": true}, + "supplier_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "attribute_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_filter_indexes" :{"limit": 10000, "ttl":"0s"}, + "resource_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_revindexes" :{"limit": 10000, "ttl":"0s"}, + "attribute_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "attribute_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, +}, + + +} \ No newline at end of file diff --git a/data/conf/samples/tutmysqlmsgpack/cgrates.json b/data/conf/samples/tutmysqlmsgpack/cgrates.json new file mode 100644 index 000000000..3e0f8f411 --- /dev/null +++ b/data/conf/samples/tutmysqlmsgpack/cgrates.json @@ -0,0 +1,67 @@ +{ +// CGRateS Configuration file +// + + +"general": { + "log_level": 7, + "dbdata_encoding": "msgpack", // encoding used to store object data in strings: +}, + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + +"data_db": { // database used to store runtime data (eg: accounts, cdr stats) + "db_type": "redis", // data_db type: + "db_port": 6379, // data_db port to reach the database + "db_name": "11", // data_db database name to connect to + +}, + +"stor_db": { + "db_password": "CGRateS.org", +}, + + +"cache":{ + "destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "rating_plans": {"limit": 10000, "ttl":"0s","precache": true}, + "rating_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "lcr_rules": {"limit": 10000, "ttl":"0s", "precache": true}, + "cdr_stats": {"limit": 10000, "ttl":"0s", "precache": true}, + "actions": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "account_action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_triggers": {"limit": 10000, "ttl":"0s", "precache": true}, + "shared_groups": {"limit": 10000, "ttl":"0s", "precache": true}, + "aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "derived_chargers": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resources": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueues": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueue_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "thresholds": {"limit": 10000, "ttl":"0s", "precache": true}, + "threshold_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "filters": {"limit": 10000, "ttl":"0s", "precache": true}, + "supplier_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "attribute_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_filter_indexes" :{"limit": 10000, "ttl":"0s"}, + "resource_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_revindexes" :{"limit": 10000, "ttl":"0s"}, + "attribute_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "attribute_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, +}, + + +} \ No newline at end of file diff --git a/data/tutorials/asterisk_ari/cgrates/etc/cgrates/cgrates.json b/data/tutorials/asterisk_ari/cgrates/etc/cgrates/cgrates.json index 036565064..1d16f47cd 100644 --- a/data/tutorials/asterisk_ari/cgrates/etc/cgrates/cgrates.json +++ b/data/tutorials/asterisk_ari/cgrates/etc/cgrates/cgrates.json @@ -4,61 +4,80 @@ // Copyright (C) ITsysCOM GmbH "general": { - "http_skip_tls_verify": false, // if enabled Http Client will accept any TLS certificate - "rounding_decimals": 5, // system level precision for floats - "dbdata_encoding": "msgpack", // encoding used to store object data in strings: - "tpexport_dir": "/var/spool/cgrates/tpe", // path towards export folder for offline Tariff Plans - "httpposter_attempts": 3, // number of http attempts before considering request failed (eg: *call_url) - "default_request_type": "*rated", // default request type to consider when missing from requests: <""|*prepaid|*postpaid|*pseudoprepaid|*rated> - "default_category": "call", // default category to consider when missing from requests - "default_tenant": "cgrates.org", // default tenant to consider when missing from requests - "default_timezone": "Local", // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB> - "connect_attempts": 3, // initial server connect attempts - "reconnects": -1, // number of retries in case of connection lost - "connect_timeout": "1s", // consider connection unsuccessful on timeout, 0 to disable the feature - "reply_timeout": "2s", // consider connection down for replies taking longer than this value - "response_cache_ttl": "0s", // the life span of a cached response - "internal_ttl": "2m", // maximum duration to wait for internal connections before giving up - "locking_timeout": "5s", // timeout internal locks to avoid deadlocks - "cache_dump_dir": "", // cache dump for faster start (leave empty to disable) + "log_level": 7, }, -"rals": { - "enabled": true, - "cdrstats_conns": [ - {"address": "*internal"} - ], - "pubsubs_conns": [ - {"address": "*internal"} - ], - "users_conns": [ - {"address": "*internal"} - ], - "aliases_conns": [ - {"address": "*internal"} - ], +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", }, -"stor_db": { // database used to store offline tariff plans and CDRs - "db_password": "CGRateS.org", // password to use when connecting to stordb + +"stor_db": { + "db_password": "CGRateS.org", }, + "scheduler": { "enabled": true, }, -"cdrs": { - "enabled": true, // start the CDR Server service: - "cdrstats_conns": [ +"rals": { + "enabled": true, + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "pubsubs_conns": [ {"address": "*internal"} ], + "attributes_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], }, -"cdrstats": { - "enabled": true, // starts the cdrstats service: +"cdrs": { + "enabled": true, + "sessions_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "sessions_cost_retries": 5, +}, + + +"sessions": { + "enabled": true, + "rals_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "cdrs_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "resources_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "suppliers_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "attributes_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "stats_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "thresholds_conns": [ + {"address": "127.0.0.1:2012", "transport": "*json"} + ], + "debit_interval": "10s", }, @@ -125,33 +144,68 @@ }, -"sessions": { - "enabled": true, - "debit_interval": "5s", // interval to perform debits on. -}, - -"sm_asterisk": { - "enabled": true, // starts Asterisk SessionManager service: +"asterisk_agent": { + "enabled": true, + "sessions_conns": [ + {"address": "*internal"} + ], "create_cdr": true, - "asterisk_conns":[ // instantiate connections to multiple Asterisk servers + "asterisk_conns":[ {"address": "127.0.0.1:8088", "user": "cgrates", "password": "CGRateS.org", "connect_attempts": 3,"reconnects": 10} ], }, "pubsubs": { - "enabled": true, // starts PubSub service: . + "enabled": true, }, -"aliases": { - "enabled": true, // starts PubSub service: . +"attributes": { + "enabled": true, + "string_indexed_fields": ["Account"], }, -"users": { - "enabled": true, // starts User service: . - "indexes": ["Uuid"], // user profile field indexes +"resources": { + "enabled": true, + "thresholds_conns": [ + {"address": "*internal"} + ], + "string_indexed_fields": ["Account"], + "prefix_indexed_fields": ["Destination"], }, + +"stats": { + "enabled": true, + "thresholds_conns": [ + {"address": "*internal"} + ], + "string_indexed_fields": ["Account"], +}, + + +"thresholds": { + "enabled": true, + "string_indexed_fields": ["Account"], +}, + + +"suppliers": { + "enabled": true, + "rals_conns": [ + {"address": "*internal"} + ], + "resources_conns": [ + {"address": "*internal"} + ], + "stats_conns": [ + {"address": "*internal"} + ], + "string_indexed_fields": ["Account"], + "prefix_indexed_fields": ["Destination"], +}, + + } diff --git a/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json b/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json index a5ac8db22..d101aa818 100644 --- a/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json +++ b/data/tutorials/kamevapi/cgrates/etc/cgrates/cgrates.json @@ -1,15 +1,13 @@ { -// Real-time Charging System for Telecom & ISP environments +// Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments // Copyright (C) ITsysCOM GmbH -// -// This file contains the default configuration hardcoded into CGRateS. -// This is what you get when you load CGRateS with an empty configuration file. "general": { "log_level": 7, }, + "listen": { "rpc_json": ":2012", "rpc_gob": ":2013", diff --git a/general_tests/tutorial_astevents_calls_test.go b/general_tests/tutorial_astevents_calls_test.go deleted file mode 100644 index 218cb6f74..000000000 --- a/general_tests/tutorial_astevents_calls_test.go +++ /dev/null @@ -1,484 +0,0 @@ -// +build calls - -/* -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 general_tests - -import ( - "net/rpc" - "net/rpc/jsonrpc" - "os" - "path" - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/apier/v1" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" -) - -const astPassword = "CGRateS.org" - -var tutAstCallsCfg *config.CGRConfig -var tutAstCallsRpc *rpc.Client -var tutAstCallsPjSuaListener *os.File - -func TestTutAstCallsInitCfg(t *testing.T) { - // Init config first - var err error - tutAstCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "asterisk_ari", "cgrates", "etc", "cgrates")) - if err != nil { - t.Error(err) - } - tutAstCallsCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() - config.SetCgrConfig(tutAstCallsCfg) -} - -// Remove data in both rating and accounting db -func TestTutAstCallsResetDataDb(t *testing.T) { - if err := engine.InitDataDb(tutAstCallsCfg); err != nil { - t.Fatal(err) - } -} - -// Wipe out the cdr database -func TestTutAstCallsResetStorDb(t *testing.T) { - if err := engine.InitStorDb(tutAstCallsCfg); err != nil { - t.Fatal(err) - } -} - -// start Asterisk server -func TestTutAstCallsStartAsterisk(t *testing.T) { - engine.KillProcName("asterisk", 1000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "asterisk_ari", "asterisk", "etc", "init.d", "asterisk"), "start", 2000); err != nil { - t.Fatal(err) - } -} - -// Start CGR Engine -func TestTutAstCallsStartEngine(t *testing.T) { - engine.KillProcName("cgr-engine", *waitRater) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "asterisk_ari", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { - t.Fatal(err) - } -} - -/* -// Restart FS so we make sure reconnects are working -func TestTutAstCallsRestartAsterisk(t *testing.T) { - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "asterisk_ari", "asterisk", "etc", "init.d", "asterisk"), "restart", 2000); err != nil { - t.Fatal(err) - } -} -*/ -// Connect rpc client to rater -func TestTutAstCallsRpcConn(t *testing.T) { - var err error - tutAstCallsRpc, err = jsonrpc.Dial("tcp", tutAstCallsCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed - if err != nil { - t.Fatal(err) - } -} - -// Load the tariff plan, creating accounts and their balances -func TestTutAstCallsLoadTariffPlanFromFolder(t *testing.T) { - reply := "" - attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")} - if err := tutAstCallsRpc.Call("ApierV1.LoadTariffPlanFromFolder", attrs, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Error(reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups -} - -// Make sure account was debited properly -func TestTutAstCallsAccountsBefore(t *testing.T) { - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutAstCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002"} - if err := tutAstCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003"} - if err := tutAstCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004"} - if err := tutAstCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007"} - if err := tutAstCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 0.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005"} - if err := tutAstCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() { - t.Error("Got error on ApierV2.GetAccount: %v", err) - } -} - -// Make sure all stats queues are in place -func TestTutAstCallsCdrStatsBefore(t *testing.T) { - //eQueueIds := []string{"*default", "CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"} - var statMetrics map[string]float64 - eMetrics := map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutAstCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACC: -1, engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1} - if err := tutAstCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutAstCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutAstCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutAstCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutAstCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } -} - -// Start Pjsua as listener and register it to receive calls -func TestTutAstCallsStartPjsuaListener(t *testing.T) { - var err error - acnts := []*engine.PjsuaAccount{ - &engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: astPassword, Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: astPassword, Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: astPassword, Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: astPassword, Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: astPassword, Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: astPassword, Realm: "*", Registrar: "sip:127.0.0.1:5060"}} - if tutAstCallsPjSuaListener, err = engine.StartPjsuaListener(acnts, 5070, time.Duration(500*time.Millisecond)); err != nil { - t.Fatal(err) - } -} - -// Call from 1001 (prepaid) to 1002 -func TestTutAstCallsCall1001To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: astPassword, Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(67)*time.Second, 5071); err != nil { - t.Fatal(err) - } -} - -// Call from 1001 (prepaid) to 1003 -func TestTutAstCallsCall1001To1003(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: astPassword, Realm: "*"}, "sip:1003@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(65)*time.Second, 5072); err != nil { - t.Fatal(err) - } -} - -func TestTutAstCallsCall1002To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: astPassword, Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5073); err != nil { - t.Fatal(err) - } -} - -func TestTutAstCallsCall1003To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: astPassword, Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5074); err != nil { - t.Fatal(err) - } -} - -func TestTutAstCallsCall1004To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: astPassword, Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5075); err != nil { - t.Fatal(err) - } -} - -func TestTutAstCallsCall1006To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: astPassword, Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5076); err != nil { - t.Fatal(err) - } -} - -func TestTutAstCallsCall1007To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: astPassword, Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5077); err != nil { - t.Fatal(err) - } -} - -// Make sure account was debited properly -func TestTutAstCallsAccount1001(t *testing.T) { - time.Sleep(time.Duration(70) * time.Second) // Allow calls to finish before start querying the results - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutAstCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() == 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } else if reply.Disabled == true { - t.Error("Account disabled") - } -} - -// Make sure account was debited properly -func TestTutAstCalls1001Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - //var cgrId string // Share with getCostDetails - //var cCost engine.CallCost - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1002"}} - if err := tutAstCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - //cgrId = reply[0].CGRID - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Usage != "67" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost == -1.0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - //if reply[0].Supplier != "suppl2" { // Usage as seconds - // t.Errorf("Unexpected Supplier for CDR: %+v", reply[0]) - //} - } - req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1003"}} - if err := tutAstCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - //cgrId = reply[0].CGRID - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost != 0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - } - req = utils.RPCCDRsFilter{Accounts: []string{"1001"}, RunIDs: []string{"derived_run1"}} - if err := tutAstCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 2 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].RequestType != utils.META_RATED { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Subject != "1002" { - t.Errorf("Unexpected Subject for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutAstCalls1002Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1002"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutAstCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 2 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_POSTPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "61" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } -} - -// Make sure account was debited properly -func TestTutAstCalls1003Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1003"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutAstCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PSEUDOPREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "63" && reply[0].Usage != "64" { // Usage as seconds, sometimes takes a second longer to disconnect - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutAstCalls1004Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1004"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutAstCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_RATED { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "62" && reply[0].Usage != "63" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } - -} - -// Make sure aliasing was done for 1006 and we have no CDRs for it -func TestTutAstCalls1006Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1006"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutAstCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 0 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } -} - -// Make sure account was debited properly -func TestTutAstCalls1007Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1007"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutAstCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1002" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "66" && reply[0].Usage != "67" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost == -1.0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - } -} - -// Make sure account was debited properly -func TestTutAstCallsAccountFraud1001(t *testing.T) { - var reply string - attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Value: 101} - if err := tutAstCallsRpc.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil { - t.Error("Got error on ApierV1.AddBalance: ", err.Error()) - } else if reply != "OK" { - t.Errorf("Calling ApierV1.AddBalance received: %s", reply) - } -} - -// Based on Fraud automatic mitigation, our account should be disabled -func TestTutAstCallsAccountDisabled1001(t *testing.T) { - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutAstCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.Disabled == false { - t.Error("Account should be disabled per fraud detection rules.") - } -} - -func TestTutAstCallsStopPjsuaListener(t *testing.T) { - time.Sleep(70 * time.Second) // Give time for calls to go through before unregistering - tutAstCallsPjSuaListener.Write([]byte("q\n")) // Close pjsua - time.Sleep(time.Duration(1) * time.Second) // Allow pjsua to finish it's tasks, eg un-REGISTER -} - -func TestTutAstCallsStopCgrEngine(t *testing.T) { - if err := engine.KillEngine(100); err != nil { - t.Error(err) - } -} - -func TestTutAstCallsStopAsterisk(t *testing.T) { - engine.KillProcName("asterisk", 100) -} diff --git a/general_tests/tut_fs_calls_test.go b/general_tests/tutorial_calls_test.go similarity index 79% rename from general_tests/tut_fs_calls_test.go rename to general_tests/tutorial_calls_test.go index ff65357b8..c129c0b31 100755 --- a/general_tests/tut_fs_calls_test.go +++ b/general_tests/tutorial_calls_test.go @@ -1,4 +1,4 @@ -// +build newcall +// +build call /* Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments @@ -22,7 +22,6 @@ package general_tests import ( "flag" - "fmt" "net/rpc" "net/rpc/jsonrpc" "os" @@ -37,14 +36,15 @@ import ( "github.com/cgrates/cgrates/utils" ) -var tutFsCallsCfg *config.CGRConfig -var tutFsCallsRpc *rpc.Client -var tutFsCallsPjSuaListener *os.File +var tutorialCallsCfg *config.CGRConfig +var tutorialCallsRpc *rpc.Client +var tutorialCallsPjSuaListener *os.File var waitRater = flag.Int("wait_rater", 100, "Number of miliseconds to wait for rater to start and cache") var dataDir = flag.String("data_dir", "/usr/share/cgrates", "CGR data dir path here") var fsConfig = flag.String("fsConfig", "/usr/share/cgrates/tutorials/fs_evsock", "FreeSwitch tutorial folder") var kamConfig = flag.String("kamConfig", "/usr/share/cgrates/tutorials/kamevapi", "Kamailio tutorial folder") var oSipsConfig = flag.String("osConfig", "/usr/share/cgrates/tutorials/osips_native", "OpenSips tutorial folder") +var ariConf = flag.String("ariConf", "/usr/share/cgrates/tutorials/asterisk_ari", "Asterisk tutorial folder") var optConf string var sTestsCalls = []func(t *testing.T){ @@ -80,61 +80,75 @@ var sTestsCalls = []func(t *testing.T){ } //Test start here -func TestFSCalls(t *testing.T) { +func TestFreeswitchCalls(t *testing.T) { optConf = utils.Freeswitch for _, stest := range sTestsCalls { t.Run("", stest) } } -func TestKamCalls(t *testing.T) { +func TestKamailioCalls(t *testing.T) { optConf = utils.Kamailio for _, stest := range sTestsCalls { t.Run("", stest) } } -func TestOSCalls(t *testing.T) { +func TestOpensipsCalls(t *testing.T) { optConf = utils.Opensips for _, stest := range sTestsCalls { t.Run("", stest) } } +/* Need to be checked +func TestAsteriskCalls(t *testing.T) { + optConf = utils.Asterisk + for _, stest := range sTestsCalls { + t.Run("", stest) + } +} +*/ + func testCallInitCfg(t *testing.T) { // Init config first var err error if optConf == utils.Freeswitch { - tutFsCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*fsConfig, "cgrates", "etc", "cgrates")) + tutorialCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*fsConfig, "cgrates", "etc", "cgrates")) if err != nil { t.Error(err) } } else if optConf == utils.Kamailio { - tutFsCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*kamConfig, "cgrates", "etc", "cgrates")) + tutorialCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*kamConfig, "cgrates", "etc", "cgrates")) if err != nil { t.Error(err) } } else if optConf == utils.Opensips { - tutFsCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*oSipsConfig, "cgrates", "etc", "cgrates")) + tutorialCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*oSipsConfig, "cgrates", "etc", "cgrates")) + if err != nil { + t.Error(err) + } + } else if optConf == utils.Asterisk { + tutorialCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*ariConf, "cgrates", "etc", "cgrates")) if err != nil { t.Error(err) } } - tutFsCallsCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() - config.SetCgrConfig(tutFsCallsCfg) + tutorialCallsCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() + config.SetCgrConfig(tutorialCallsCfg) } // Remove data in both rating and accounting db func testCallResetDataDb(t *testing.T) { - if err := engine.InitDataDb(tutFsCallsCfg); err != nil { + if err := engine.InitDataDb(tutorialCallsCfg); err != nil { t.Fatal(err) } } // Wipe out the cdr database func testCallResetStorDb(t *testing.T) { - if err := engine.InitStorDb(tutFsCallsCfg); err != nil { + if err := engine.InitStorDb(tutorialCallsCfg); err != nil { t.Fatal(err) } } @@ -156,6 +170,11 @@ func testCallStartFS(t *testing.T) { if err := engine.CallScript(path.Join(*oSipsConfig, "opensips", "etc", "init.d", "opensips"), "start", 3000); err != nil { t.Fatal(err) } + } else if optConf == utils.Asterisk { + engine.KillProcName(utils.Asterisk, 5000) + if err := engine.CallScript(path.Join(*ariConf, "asterisk", "etc", "init.d", "asterisk"), "start", 3000); err != nil { + t.Fatal(err) + } } } @@ -174,6 +193,10 @@ func testCallStartEngine(t *testing.T) { if err := engine.CallScript(path.Join(*oSipsConfig, "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { t.Fatal(err) } + } else if optConf == utils.Asterisk { + if err := engine.CallScript(path.Join(*ariConf, "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { + t.Fatal(err) + } } } @@ -191,13 +214,17 @@ func testCallRestartFS(t *testing.T) { if err := engine.CallScript(path.Join(*oSipsConfig, "opensips", "etc", "init.d", "opensips"), "restart", 5000); err != nil { t.Fatal(err) } + } else if optConf == utils.Asterisk { + if err := engine.CallScript(path.Join(*ariConf, "asterisk", "etc", "init.d", "asterisk"), "restart", 5000); err != nil { + t.Fatal(err) + } } } // Connect rpc client to rater func testCallRpcConn(t *testing.T) { var err error - tutFsCallsRpc, err = jsonrpc.Dial("tcp", tutFsCallsCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed + tutorialCallsRpc, err = jsonrpc.Dial("tcp", tutorialCallsCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed if err != nil { t.Fatal(err) } @@ -208,7 +235,7 @@ func testCallRpcConn(t *testing.T) { func testCallLoadTariffPlanFromFolder(t *testing.T) { var reply string attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial2")} - if err := tutFsCallsRpc.Call("ApierV1.LoadTariffPlanFromFolder", attrs, &reply); err != nil { + if err := tutorialCallsRpc.Call("ApierV1.LoadTariffPlanFromFolder", attrs, &reply); err != nil { t.Error(err) } time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups @@ -218,14 +245,14 @@ func testCallLoadTariffPlanFromFolder(t *testing.T) { func testCallAccountsBefore(t *testing.T) { var reply *engine.Account attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { + if err := tutorialCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { t.Error("Got error on ApierV2.GetAccount: ", err.Error()) } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) } var reply2 *engine.Account attrs2 := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs2, &reply2); err != nil { + if err := tutorialCallsRpc.Call("ApierV2.GetAccount", attrs2, &reply2); err != nil { t.Error("Got error on ApierV2.GetAccount: ", err.Error()) } else if reply2.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { t.Errorf("Calling ApierV1.GetBalance received: %f", reply2.BalanceMap[utils.MONETARY].GetTotalValue()) @@ -238,7 +265,7 @@ func testCallStatMetricsBefore(t *testing.T) { utils.MetaTCC: utils.NOT_AVAILABLE, utils.MetaTCD: utils.NOT_AVAILABLE, } - if err := tutFsCallsRpc.Call(utils.StatSv1GetQueueStringMetrics, + if err := tutorialCallsRpc.Call(utils.StatSv1GetQueueStringMetrics, &utils.TenantID{Tenant: "cgrates.org", ID: "Stats2"}, &metrics); err != nil { t.Error(err) } else if !reflect.DeepEqual(expectedMetrics, metrics) { @@ -257,7 +284,7 @@ func testCallCheckResourceBeforeAllocation(t *testing.T) { utils.Subject: "1001", utils.Destination: "1002"}, }} - if err := tutFsCallsRpc.Call(utils.ResourceSv1GetResourcesForEvent, args, &rs); err != nil { + if err := tutorialCallsRpc.Call(utils.ResourceSv1GetResourcesForEvent, args, &rs); err != nil { t.Error(err) } else if len(*rs) != 2 { t.Errorf("Resources: %+v", utils.ToJSON(rs)) @@ -273,7 +300,7 @@ func testCallCheckResourceBeforeAllocation(t *testing.T) { func testCallCheckThreshold1001Before(t *testing.T) { var td engine.Threshold eTd := engine.Threshold{Tenant: "cgrates.org", ID: "THD_ACNT_1001", Hits: 0} - if err := tutFsCallsRpc.Call(utils.ThresholdSv1GetThreshold, + if err := tutorialCallsRpc.Call(utils.ThresholdSv1GetThreshold, &utils.TenantID{Tenant: "cgrates.org", ID: "THD_ACNT_1001"}, &td); err != nil { t.Error(err) } else if !reflect.DeepEqual(eTd, td) { @@ -284,7 +311,7 @@ func testCallCheckThreshold1001Before(t *testing.T) { func testCallCheckThreshold1002Before(t *testing.T) { var td engine.Threshold eTd := engine.Threshold{Tenant: "cgrates.org", ID: "THD_ACNT_1002", Hits: 0} - if err := tutFsCallsRpc.Call(utils.ThresholdSv1GetThreshold, + if err := tutorialCallsRpc.Call(utils.ThresholdSv1GetThreshold, &utils.TenantID{Tenant: "cgrates.org", ID: "THD_ACNT_1002"}, &td); err != nil { t.Error(err) } else if !reflect.DeepEqual(eTd, td) { @@ -303,7 +330,7 @@ func testCallStartPjsuaListener(t *testing.T) { &engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5080"}, } - if tutFsCallsPjSuaListener, err = engine.StartPjsuaListener( + if tutorialCallsPjSuaListener, err = engine.StartPjsuaListener( acnts, 5070, time.Duration(*waitRater)*time.Millisecond); err != nil { t.Fatal(err) } @@ -332,7 +359,7 @@ func testCallGetActiveSessions(t *testing.T) { Destination: "1002", }, } - if err := tutFsCallsRpc.Call(utils.SessionSv1GetActiveSessions, + if err := tutorialCallsRpc.Call(utils.SessionSv1GetActiveSessions, &map[string]string{}, &reply); err != nil { t.Error("Got error on SessionSv1.GetActiveSessions: ", err.Error()) } else { @@ -377,7 +404,7 @@ func testCallCheckResourceAllocation(t *testing.T) { utils.Subject: "1001", utils.Destination: "1002"}, }} - if err := tutFsCallsRpc.Call(utils.ResourceSv1GetResourcesForEvent, args, &rs); err != nil { + if err := tutorialCallsRpc.Call(utils.ResourceSv1GetResourcesForEvent, args, &rs); err != nil { t.Error(err) } else if len(*rs) != 2 { t.Errorf("Resources: %+v", utils.ToJSON(rs)) @@ -395,7 +422,7 @@ func testCallAccount1001(t *testing.T) { time.Sleep(time.Duration(80) * time.Second) // Allow calls to finish before start querying the results var reply *engine.Account attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { + if err := tutorialCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { t.Error(err.Error()) } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() == 10.0 { // Make sure we debitted t.Errorf("Expected: 10, received: %+v", reply.BalanceMap[utils.MONETARY].GetTotalValue()) @@ -408,15 +435,12 @@ func testCallAccount1001(t *testing.T) { func testCall1001Cdrs(t *testing.T) { var reply []*engine.ExternalCDR req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { + if err := tutorialCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 2 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { for _, cdr := range reply { - if cdr.Source != "freeswitch_json" && cdr.Source != "SMG_KamailioAgent" { - t.Errorf("Unexpected Source for CDR: %+v", cdr.Source) - } if cdr.RequestType != utils.META_PREPAID { t.Errorf("Unexpected RequestType for CDR: %+v", cdr.RequestType) } @@ -443,14 +467,11 @@ func testCall1001Cdrs(t *testing.T) { func testCall1002Cdrs(t *testing.T) { var reply []*engine.ExternalCDR req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1002"}, DestinationPrefixes: []string{"1001"}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { + if err := tutorialCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(reply) != 1 { t.Error("Unexpected number of CDRs returned: ", len(reply)) } else { - if reply[0].Source != "freeswitch_json" && reply[0].Source != "SMG_KamailioAgent" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0].Source) - } if reply[0].RequestType != utils.META_POSTPAID { t.Errorf("Unexpected RequestType for CDR: %+v", reply[0].RequestType) } @@ -473,7 +494,7 @@ func testCallStatMetrics(t *testing.T) { utils.MetaTCC: "1.34009", utils.MetaTCD: "2m24s", } - if err := tutFsCallsRpc.Call(utils.StatSv1GetQueueStringMetrics, + if err := tutorialCallsRpc.Call(utils.StatSv1GetQueueStringMetrics, &utils.TenantID{Tenant: "cgrates.org", ID: "Stats2"}, &metrics); err != nil { t.Error(err) } else if !reflect.DeepEqual(expectedMetrics1, metrics) && @@ -493,7 +514,7 @@ func testCallCheckResourceRelease(t *testing.T) { utils.Subject: "1001", utils.Destination: "1002"}, }} - if err := tutFsCallsRpc.Call(utils.ResourceSv1GetResourcesForEvent, args, &rs); err != nil { + if err := tutorialCallsRpc.Call(utils.ResourceSv1GetResourcesForEvent, args, &rs); err != nil { t.Error(err) } else if len(*rs) != 2 { t.Errorf("Resources: %+v", rs) @@ -508,7 +529,7 @@ func testCallCheckResourceRelease(t *testing.T) { func testCallCheckThreshold1001After(t *testing.T) { var td engine.Threshold - if err := tutFsCallsRpc.Call(utils.ThresholdSv1GetThreshold, + if err := tutorialCallsRpc.Call(utils.ThresholdSv1GetThreshold, &utils.TenantID{Tenant: "cgrates.org", ID: "THD_ACNT_1001"}, &td); err != nil && err.Error() != utils.ErrNotFound.Error() { t.Error(err) @@ -518,7 +539,7 @@ func testCallCheckThreshold1001After(t *testing.T) { func testCallCheckThreshold1002After(t *testing.T) { var td engine.Threshold eTd := engine.Threshold{Tenant: "cgrates.org", ID: "THD_ACNT_1002", Hits: 4} - if err := tutFsCallsRpc.Call(utils.ThresholdSv1GetThreshold, + if err := tutorialCallsRpc.Call(utils.ThresholdSv1GetThreshold, &utils.TenantID{Tenant: "cgrates.org", ID: "THD_ACNT_1002"}, &td); err != nil { t.Error(err) } else if !reflect.DeepEqual(eTd.Tenant, td.Tenant) { @@ -531,8 +552,8 @@ func testCallCheckThreshold1002After(t *testing.T) { } func testCallStopPjsuaListener(t *testing.T) { - tutFsCallsPjSuaListener.Write([]byte("q\n")) // Close pjsua - time.Sleep(time.Duration(1) * time.Second) // Allow pjsua to finish it's tasks, eg un-REGISTER + tutorialCallsPjSuaListener.Write([]byte("q\n")) // Close pjsua + time.Sleep(time.Duration(1) * time.Second) // Allow pjsua to finish it's tasks, eg un-REGISTER } func testCallStopCgrEngine(t *testing.T) { @@ -548,5 +569,7 @@ func testCallStopFS(t *testing.T) { engine.KillProcName(utils.Kamailio, 1000) } else if optConf == utils.Opensips { engine.KillProcName(utils.Opensips, 1000) + } else if optConf == utils.Asterisk { + engine.KillProcName(utils.Asterisk, 1000) } } diff --git a/general_tests/tutorial_fs_calls_test.go b/general_tests/tutorial_fs_calls_test.go deleted file mode 100644 index 4bcd8987c..000000000 --- a/general_tests/tutorial_fs_calls_test.go +++ /dev/null @@ -1,497 +0,0 @@ -// +build calls - -/* -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 general_tests - -import ( - "net/rpc" - "net/rpc/jsonrpc" - "os" - "path" - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/apier/v1" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" -) - -var tutFsCallsCfg *config.CGRConfig -var tutFsCallsRpc *rpc.Client -var tutFsCallsPjSuaListener *os.File - -func TestTutFsCallsInitCfg(t *testing.T) { - // Init config first - var err error - tutFsCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "fs_evsock", "cgrates", "etc", "cgrates")) - if err != nil { - t.Error(err) - } - tutFsCallsCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() - config.SetCgrConfig(tutFsCallsCfg) -} - -// Remove data in both rating and accounting db -func TestTutFsCallsResetDataDb(t *testing.T) { - if err := engine.InitDataDb(tutFsCallsCfg); err != nil { - t.Fatal(err) - } -} - -// Wipe out the cdr database -func TestTutFsCallsResetStorDb(t *testing.T) { - if err := engine.InitStorDb(tutFsCallsCfg); err != nil { - t.Fatal(err) - } -} - -// start FS server -func TestTutFsCallsStartFS(t *testing.T) { - engine.KillProcName("freeswitch", 5000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 3000); err != nil { - t.Fatal(err) - } -} - -// Start CGR Engine -func TestTutFsCallsStartEngine(t *testing.T) { - engine.KillProcName("cgr-engine", *waitRater) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { - t.Fatal(err) - } -} - -// Restart FS so we make sure reconnects are working -func TestTutFsCallsRestartFS(t *testing.T) { - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "restart", 5000); err != nil { - t.Fatal(err) - } -} - -// Connect rpc client to rater -func TestTutFsCallsRpcConn(t *testing.T) { - var err error - tutFsCallsRpc, err = jsonrpc.Dial("tcp", tutFsCallsCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed - if err != nil { - t.Fatal(err) - } -} - -// Load the tariff plan, creating accounts and their balances -func TestTutFsCallsLoadTariffPlanFromFolder(t *testing.T) { - reply := "" - attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")} - if err := tutFsCallsRpc.Call("ApierV1.LoadTariffPlanFromFolder", attrs, &reply); err != nil { - t.Error(err) - } else if reply != "OK" { - t.Error(reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups -} - -// Make sure account was debited properly -func TestTutFsCallsAccountsBefore(t *testing.T) { - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 0.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() { - t.Errorf("Got error on ApierV2.GetAccount: %v", err) - } -} - -// Make sure all stats queues are in place -func TestTutFsCallsCdrStatsBefore(t *testing.T) { - //eQueueIds := []string{"*default", "CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"} - var statMetrics map[string]float64 - eMetrics := map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACC: -1, engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1} - if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } -} - -// Start Pjsua as listener and register it to receive calls -func TestTutFsCallsStartPjsuaListener(t *testing.T) { - var err error - acnts := []*engine.PjsuaAccount{ - &engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}} - if tutFsCallsPjSuaListener, err = engine.StartPjsuaListener(acnts, 5070, time.Duration(*waitRater)*time.Millisecond); err != nil { - t.Fatal(err) - } -} - -// Call from 1001 (prepaid) to 1002 -func TestTutFsCallsCall1001To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(67)*time.Second, 5071); err != nil { - t.Fatal(err) - } -} - -// Call from 1001 (prepaid) to 1003 -func TestTutFsCallsCall1001To1003(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1003@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(65)*time.Second, 5072); err != nil { - t.Fatal(err) - } -} - -func TestTutFsCallsCall1002To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5073); err != nil { - t.Fatal(err) - } -} - -func TestTutFsCallsCall1003To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5074); err != nil { - t.Fatal(err) - } -} - -func TestTutFsCallsCall1004To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5075); err != nil { - t.Fatal(err) - } -} - -func TestTutFsCallsCall1006To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5076); err != nil { - t.Fatal(err) - } -} - -func TestTutFsCallsCall1007To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5077); err != nil { - t.Fatal(err) - } -} - -// Make sure account was debited properly -func TestTutFsCallsAccount1001(t *testing.T) { - time.Sleep(time.Duration(80) * time.Second) // Allow calls to finish before start querying the results - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() == 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } else if reply.Disabled == true { - t.Error("Account disabled") - } -} - -// Make sure account was debited properly -func TestTutFsCalls1001Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - //var CGRID string // Share with getCostDetails - //var cCost engine.CallCost - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1002"}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - //CGRID = reply[0].CGRID - if reply[0].Source != "freeswitch_json" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Usage != "67" && reply[0].Usage != "68" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost == -1.0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - //if reply[0].Supplier != "suppl2" { // Usage as seconds - // t.Errorf("Unexpected Supplier for CDR: %+v", reply[0]) - //} - } - /* - // Make sure call cost contains the matched information - if err := tutFsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: CGRID}, &cCost); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") { - t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0]) - } - */ - - req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1003"}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - //CGRID = reply[0].CGRID - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost != 0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - } - /* - // Make sure call cost contains the matched information - if err := tutFsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: CGRID}, &cCost); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") { - t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0]) - } - */ - req = utils.RPCCDRsFilter{Accounts: []string{"1001"}, RunIDs: []string{"derived_run1"}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 2 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].RequestType != utils.META_RATED { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Subject != "1002" { - t.Errorf("Unexpected Subject for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutFsCalls1002Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1002"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 2 { // Should be counted here also call originated form 1006 which is aliased to 1002 - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "freeswitch_json" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_POSTPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "61" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } -} - -// Make sure account was debited properly -func TestTutFsCalls1003Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1003"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "freeswitch_json" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PSEUDOPREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "63" && reply[0].Usage != "64" { // Usage as seconds, sometimes takes a second longer to disconnect - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutFsCalls1004Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1004"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "freeswitch_json" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_RATED { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "62" && reply[0].Usage != "63" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } - -} - -// Make sure we don't have any CDRs for 1006 since it should have been aliased to 1002 -func TestTutFsCalls1006Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1006"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 0 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } -} - -// Make sure account was debited properly -func TestTutFsCalls1007Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1007"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "freeswitch_json" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1002" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "66" && reply[0].Usage != "67" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost == -1.0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - } -} - -// Make sure account was debited properly -func TestTutFsCallsAccountFraud1001(t *testing.T) { - var reply string - attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Value: 101} - if err := tutFsCallsRpc.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil { - t.Error("Got error on ApierV1.AddBalance: ", err.Error()) - } else if reply != "OK" { - t.Errorf("Calling ApierV1.AddBalance received: %s", reply) - } -} - -// Based on Fraud automatic mitigation, our account should be disabled -func TestTutFsCallsAccountDisabled1001(t *testing.T) { - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutFsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.Disabled == false { - t.Error("Account should be disabled per fraud detection rules.") - } -} - -func TestTutFsCallsStopPjsuaListener(t *testing.T) { - tutFsCallsPjSuaListener.Write([]byte("q\n")) // Close pjsua - time.Sleep(time.Duration(1) * time.Second) // Allow pjsua to finish it's tasks, eg un-REGISTER -} - -func TestTutFsCallsStopCgrEngine(t *testing.T) { - if err := engine.KillEngine(100); err != nil { - t.Error(err) - } -} - -func TestTutFsCallsStopFS(t *testing.T) { - engine.KillProcName("freeswitch", 1000) -} diff --git a/general_tests/tutorial_kam_calls_test.go b/general_tests/tutorial_kam_calls_test.go deleted file mode 100644 index 0254d2e12..000000000 --- a/general_tests/tutorial_kam_calls_test.go +++ /dev/null @@ -1,496 +0,0 @@ -// +build calls - -/* -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 general_tests - -import ( - "net/rpc" - "net/rpc/jsonrpc" - "os" - "path" - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/apier/v1" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" -) - -var tutKamCallsCfg *config.CGRConfig -var tutKamCallsRpc *rpc.Client -var tutKamCallsPjSuaListener *os.File - -func TestTutKamCallsInitCfg(t *testing.T) { - // Init config first - var err error - tutKamCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "kamevapi", "cgrates", "etc", "cgrates")) - if err != nil { - t.Error(err) - } - tutKamCallsCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() - config.SetCgrConfig(tutKamCallsCfg) -} - -// Remove data in both rating and accounting db -func TestTutKamCallsResetDataDb(t *testing.T) { - if err := engine.InitDataDb(tutKamCallsCfg); err != nil { - t.Fatal(err) - } -} - -// Wipe out the cdr database -func TestTutKamCallsResetStorDb(t *testing.T) { - if err := engine.InitStorDb(tutKamCallsCfg); err != nil { - t.Fatal(err) - } -} - -// start FS server -func TestTutKamCallsStartKamailio(t *testing.T) { - engine.KillProcName("kamailio", 3000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "start", 2000); err != nil { - t.Fatal(err) - } -} - -// Start CGR Engine -func TestTutKamCallsStartEngine(t *testing.T) { - engine.KillProcName("cgr-engine", *waitRater) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { - t.Fatal(err) - } -} - -// Restart FS so we make sure reconnects are working -func TestTutKamCallsRestartKamailio(t *testing.T) { - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "restart", 3000); err != nil { - t.Fatal(err) - } -} - -// Connect rpc client to rater -func TestTutKamCallsRpcConn(t *testing.T) { - var err error - tutKamCallsRpc, err = jsonrpc.Dial("tcp", tutKamCallsCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed - if err != nil { - t.Fatal(err) - } -} - -// Load the tariff plan, creating accounts and their balances -func TestTutKamCallsLoadTariffPlanFromFolder(t *testing.T) { - reply := "" - attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")} - if err := tutKamCallsRpc.Call("ApierV1.LoadTariffPlanFromFolder", attrs, &reply); err != nil { - t.Error(err) - } else if reply != "OK" { - t.Error(reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups -} - -// Make sure account was debited properly -func TestTutKamCallsAccountsBefore(t *testing.T) { - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutKamCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002"} - if err := tutKamCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003"} - if err := tutKamCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004"} - if err := tutKamCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007"} - if err := tutKamCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 0.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005"} - if err := tutKamCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() { - t.Errorf("Got error on ApierV2.GetAccount: %v", err) - } -} - -// Make sure all stats queues are in place -func TestTutKamCallsCdrStatsBefore(t *testing.T) { - //eQueueIds := []string{"*default", "CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"} - var statMetrics map[string]float64 - eMetrics := map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACC: -1, engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1} - if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } -} - -// Start Pjsua as listener and register it to receive calls -func TestTutKamCallsStartPjsuaListener(t *testing.T) { - var err error - acnts := []*engine.PjsuaAccount{ - &engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}} - if tutKamCallsPjSuaListener, err = engine.StartPjsuaListener(acnts, 5070, time.Duration(*waitRater)*time.Millisecond); err != nil { - t.Fatal(err) - } -} - -// Call from 1001 (prepaid) to 1002 -func TestTutKamCallsCall1001To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(67)*time.Second, 5071); err != nil { - t.Fatal(err) - } -} - -// Call from 1001 (prepaid) to 1003 -func TestTutKamCallsCall1001To1003(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*"}, "sip:1003@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(65)*time.Second, 5072); err != nil { - t.Fatal(err) - } -} - -func TestTutKamCallsCall1002To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5073); err != nil { - t.Fatal(err) - } -} - -func TestTutKamCallsCall1003To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5074); err != nil { - t.Fatal(err) - } -} - -func TestTutKamCallsCall1004To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5075); err != nil { - t.Fatal(err) - } -} - -func TestTutKamCallsCall1006To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5076); err != nil { - t.Fatal(err) - } -} - -func TestTutKamCallsCall1007To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5077); err != nil { - t.Fatal(err) - } -} - -// Make sure account was debited properly -func TestTutKamCallsAccount1001(t *testing.T) { - time.Sleep(time.Duration(70) * time.Second) // Allow calls to finish before start querying the results - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutKamCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() == 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } else if reply.Disabled == true { - t.Error("Account disabled") - } -} - -// Make sure account was debited properly -func TestTutKamCalls1001Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - //var cgrId string // Share with getCostDetails - //var cCost engine.CallCost - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1002"}} - if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - //cgrId = reply[0].CGRID - if reply[0].Source != "KAMAILIO_CGR_CALL_END" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Usage != "67" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost == -1.0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - //if reply[0].Supplier != "suppl2" { // Usage as seconds - // t.Errorf("Unexpected Supplier for CDR: %+v", reply[0]) - //} - } - /* - // Make sure call cost contains the matched information - if err := tutKamCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") { - t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0]) - } - */ - req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1003"}} - if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - //cgrId = reply[0].CGRID - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost != 0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - } - /* - // Make sure call cost contains the matched information - if err := tutKamCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") { - t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0]) - } - */ - req = utils.RPCCDRsFilter{Accounts: []string{"1001"}, RunIDs: []string{"derived_run1"}} - if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 2 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].RequestType != utils.META_RATED { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Subject != "1002" { - t.Errorf("Unexpected Subject for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutKamCalls1002Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1002"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 2 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "KAMAILIO_CGR_CALL_END" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_POSTPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "61" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } -} - -// Make sure account was debited properly -func TestTutKamCalls1003Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1003"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "KAMAILIO_CGR_CALL_END" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PSEUDOPREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "63" && reply[0].Usage != "64" { // Usage as seconds, sometimes takes a second longer to disconnect - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutKamCalls1004Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1004"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "KAMAILIO_CGR_CALL_END" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_RATED { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "62" && reply[0].Usage != "63" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutKamCalls1006Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1006"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 0 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } -} - -// Make sure account was debited properly -func TestTutKamCalls1007Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1007"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "KAMAILIO_CGR_CALL_END" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1002" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "66" && reply[0].Usage != "67" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost == -1.0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - } -} - -// Make sure account was debited properly -func TestTutKamCallsAccountFraud1001(t *testing.T) { - var reply string - attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Value: 101} - if err := tutKamCallsRpc.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil { - t.Error("Got error on ApierV1.AddBalance: ", err.Error()) - } else if reply != "OK" { - t.Errorf("Calling ApierV1.AddBalance received: %s", reply) - } -} - -// Based on Fraud automatic mitigation, our account should be disabled -func TestTutKamCallsAccountDisabled1001(t *testing.T) { - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutKamCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.Disabled == false { - t.Error("Account should be disabled per fraud detection rules.") - } -} - -func TestTutKamCallsStopPjsuaListener(t *testing.T) { - tutKamCallsPjSuaListener.Write([]byte("q\n")) // Close pjsua - time.Sleep(time.Duration(1) * time.Second) // Allow pjsua to finish it's tasks, eg un-REGISTER -} - -func TestTutKamCallsStopCgrEngine(t *testing.T) { - if err := engine.KillEngine(100); err != nil { - t.Error(err) - } -} - -func TestTutKamCallsStopKam(t *testing.T) { - engine.KillProcName("kamailio", 1000) -} diff --git a/general_tests/tutorial_osips_calls_test.go b/general_tests/tutorial_osips_calls_test.go deleted file mode 100644 index ca8c8ef47..000000000 --- a/general_tests/tutorial_osips_calls_test.go +++ /dev/null @@ -1,496 +0,0 @@ -// +build calls - -/* -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 general_tests - -import ( - "net/rpc" - "net/rpc/jsonrpc" - "os" - "path" - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/apier/v1" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" -) - -var tutOsipsCallsCfg *config.CGRConfig -var tutOsipsCallsRpc *rpc.Client -var tutOsipsCallsPjSuaListener *os.File - -func TestTutOsipsCallsInitCfg(t *testing.T) { - // Init config first - var err error - tutOsipsCallsCfg, err = config.NewCGRConfigFromFolder(path.Join(*dataDir, "tutorials", "osips_async", "cgrates", "etc", "cgrates")) - if err != nil { - t.Error(err) - } - tutOsipsCallsCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() - config.SetCgrConfig(tutOsipsCallsCfg) -} - -// Remove data in both rating and accounting db -func TestTutOsipsCallsResetDataDb(t *testing.T) { - if err := engine.InitDataDb(tutOsipsCallsCfg); err != nil { - t.Fatal(err) - } -} - -// Wipe out the cdr database -func TestTutOsipsCallsResetStorDb(t *testing.T) { - if err := engine.InitStorDb(tutOsipsCallsCfg); err != nil { - t.Fatal(err) - } -} - -// start FS server -func TestTutOsipsCallsStartOsips(t *testing.T) { - engine.KillProcName("opensips", 3000) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "start", 3000); err != nil { - t.Fatal(err) - } -} - -// Start CGR Engine -func TestTutOsipsCallsStartEngine(t *testing.T) { - engine.KillProcName("cgr-engine", *waitRater) - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "cgrates", "etc", "init.d", "cgrates"), "start", 100); err != nil { - t.Fatal(err) - } -} - -// Restart FS so we make sure reconnects are working -func TestTutOsipsCallsRestartOsips(t *testing.T) { - if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "restart", 3000); err != nil { - t.Fatal(err) - } -} - -// Connect rpc client to rater -func TestTutOsipsCallsRpcConn(t *testing.T) { - var err error - tutOsipsCallsRpc, err = jsonrpc.Dial("tcp", tutOsipsCallsCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed - if err != nil { - t.Fatal(err) - } -} - -// Load the tariff plan, creating accounts and their balances -func TestTutOsipsCallsLoadTariffPlanFromFolder(t *testing.T) { - reply := "" - attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")} - if err := tutOsipsCallsRpc.Call("ApierV1.LoadTariffPlanFromFolder", attrs, &reply); err != nil { - t.Error(err) - } else if reply != "OK" { - t.Error(reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups -} - -// Make sure account was debited properly -func TestTutOsipsCallsAccountsBefore(t *testing.T) { - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutOsipsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1002"} - if err := tutOsipsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003"} - if err := tutOsipsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1004"} - if err := tutOsipsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1007"} - if err := tutOsipsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() != 0.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } - attrs = &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1005"} - if err := tutOsipsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() { - t.Error("Got error on ApierV2.GetAccount: %v", err) - } -} - -// Make sure all stats queues are in place -func TestTutOsipsCallsCdrStatsBefore(t *testing.T) { - //eQueueIds := []string{"*default", "CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"} - var statMetrics map[string]float64 - eMetrics := map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACC: -1, engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1} - if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1} - if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } -} - -// Start Pjsua as listener and register it to receive calls -func TestTutOsipsCallsStartPjsuaListener(t *testing.T) { - var err error - acnts := []*engine.PjsuaAccount{ - &engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}, - &engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}} - if tutOsipsCallsPjSuaListener, err = engine.StartPjsuaListener(acnts, 5070, time.Duration(*waitRater)*time.Millisecond); err != nil { - t.Fatal(err) - } -} - -// Call from 1001 (prepaid) to 1002 -func TestTutOsipsCallsCall1001To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(67)*time.Second, 5071); err != nil { - t.Fatal(err) - } -} - -// Call from 1001 (prepaid) to 1003 -func TestTutOsipsCallsCall1001To1003(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1003@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(65)*time.Second, 5072); err != nil { - t.Fatal(err) - } -} - -func TestTutOsipsCallsCall1002To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5073); err != nil { - t.Fatal(err) - } -} - -func TestTutOsipsCallsCall1003To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5074); err != nil { - t.Fatal(err) - } -} - -func TestTutOsipsCallsCall1004To1001(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5075); err != nil { - t.Fatal(err) - } -} - -func TestTutOsipsCallsCall1006To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5076); err != nil { - t.Fatal(err) - } -} - -func TestTutOsipsCallsCall1007To1002(t *testing.T) { - if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1", - "sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5077); err != nil { - t.Fatal(err) - } -} - -// Make sure account was debited properly -func TestTutOsipsCallsAccount1001(t *testing.T) { - time.Sleep(time.Duration(70) * time.Second) // Allow calls to finish before start querying the results - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutOsipsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.BalanceMap[utils.MONETARY].GetTotalValue() == 10.0 { // Make sure we debitted - t.Errorf("Calling ApierV1.GetBalance received: %f", reply.BalanceMap[utils.MONETARY].GetTotalValue()) - } else if reply.Disabled == true { - t.Error("Account disabled") - } -} - -// Make sure account was debited properly -func TestTutOsipsCalls1001Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - //var cgrId string // Share with getCostDetails - //var cCost engine.CallCost - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1002"}} - if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - //cgrId = reply[0].CGRID - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Usage != "67" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost == -1.0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - //if reply[0].Supplier != "suppl2" { // Usage as seconds - // t.Errorf("Unexpected Supplier for CDR: %+v", reply[0]) - //} - } - /* - // Make sure call cost contains the matched information - if err := tutOsipsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") { - t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0]) - } - */ - req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestinationPrefixes: []string{"1003"}} - if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - //cgrId = reply[0].CGRID - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost != 0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - } - /* - // Make sure call cost contains the matched information - if err := tutOsipsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") { - t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0]) - } - */ - req = utils.RPCCDRsFilter{Accounts: []string{"1001"}, RunIDs: []string{"derived_run1"}} - if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 2 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].RequestType != utils.META_RATED { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Subject != "1002" { - t.Errorf("Unexpected Subject for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutOsipsCalls1002Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1002"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 2 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_POSTPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "61" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } -} - -// Make sure account was debited properly -func TestTutOsipsCalls1003Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1003"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PSEUDOPREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "63" && reply[0].Usage != "64" { // Usage as seconds, sometimes takes a second longer to disconnect - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } - -} - -// Make sure account was debited properly -func TestTutOsipsCalls1004Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1004"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_RATED { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1001" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "62" && reply[0].Usage != "63" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - } - -} - -// Make sure aliasing was done for 1006 and we have no CDRs for it -func TestTutOsipsCalls1006Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1006"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 0 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } -} - -// Make sure account was debited properly -func TestTutOsipsCalls1007Cdrs(t *testing.T) { - var reply []*engine.ExternalCDR - req := utils.RPCCDRsFilter{Accounts: []string{"1007"}, RunIDs: []string{utils.META_DEFAULT}} - if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(reply) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(reply)) - } else { - if reply[0].Source != "OSIPS_E_ACC_EVENT" { - t.Errorf("Unexpected Source for CDR: %+v", reply[0]) - } - if reply[0].RequestType != utils.META_PREPAID { - t.Errorf("Unexpected RequestType for CDR: %+v", reply[0]) - } - if reply[0].Destination != "1002" { - t.Errorf("Unexpected Destination for CDR: %+v", reply[0]) - } - if reply[0].Usage != "66" && reply[0].Usage != "67" { // Usage as seconds - t.Errorf("Unexpected Usage for CDR: %+v", reply[0]) - } - if reply[0].Cost == -1.0 { // Cost was not calculated - t.Errorf("Unexpected Cost for CDR: %+v", reply[0]) - } - } -} - -// Make sure account was debited properly -func TestTutOsipsCallsAccountFraud1001(t *testing.T) { - var reply string - attrAddBlnc := &v1.AttrAddBalance{Tenant: "cgrates.org", Account: "1001", BalanceType: "*monetary", Value: 101} - if err := tutOsipsCallsRpc.Call("ApierV1.AddBalance", attrAddBlnc, &reply); err != nil { - t.Error("Got error on ApierV1.AddBalance: ", err.Error()) - } else if reply != "OK" { - t.Errorf("Calling ApierV1.AddBalance received: %s", reply) - } -} - -// Based on Fraud automatic mitigation, our account should be disabled -func TestTutOsipsCallsAccountDisabled1001(t *testing.T) { - var reply *engine.Account - attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001"} - if err := tutOsipsCallsRpc.Call("ApierV2.GetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.GetAccount: ", err.Error()) - } else if reply.Disabled == false { - t.Error("Account should be disabled per fraud detection rules.") - } -} - -func TestTutOsipsCallsStopPjsuaListener(t *testing.T) { - tutOsipsCallsPjSuaListener.Write([]byte("q\n")) // Close pjsua - time.Sleep(time.Duration(1) * time.Second) // Allow pjsua to finish it's tasks, eg un-REGISTER -} - -func TestTutOsipsCallsStopCgrEngine(t *testing.T) { - if err := engine.KillEngine(100); err != nil { - t.Error(err) - } -} - -func TestTutOsipsCallsStopOpensips(t *testing.T) { - engine.KillProcName("opensips", 100) -} diff --git a/migrator/accounts_it_test.go b/migrator/accounts_it_test.go index 3e13e6dac..4c7b8b3a2 100755 --- a/migrator/accounts_it_test.go +++ b/migrator/accounts_it_test.go @@ -102,6 +102,42 @@ func TestAccountITMove(t *testing.T) { } } +func TestAccountITMoveEncoding(t *testing.T) { + var err error + accPathIn = path.Join(*dataDir, "conf", "samples", "tutmongojson") + accCfgIn, err = config.NewCGRConfigFromFolder(accPathIn) + if err != nil { + t.Fatal(err) + } + accPathOut = path.Join(*dataDir, "conf", "samples", "tutmongomsgpack") + accCfgOut, err = config.NewCGRConfigFromFolder(accPathOut) + if err != nil { + t.Fatal(err) + } + accAction = utils.Move + for _, stest := range sTestsAccIT { + t.Run("TestAccountITMove", stest) + } +} + +func TestAccountITMoveEncoding2(t *testing.T) { + var err error + accPathIn = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + accCfgIn, err = config.NewCGRConfigFromFolder(accPathIn) + if err != nil { + t.Fatal(err) + } + accPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqlmsgpack") + accCfgOut, err = config.NewCGRConfigFromFolder(accPathOut) + if err != nil { + t.Fatal(err) + } + accAction = utils.Move + for _, stest := range sTestsAccIT { + t.Run("TestAccountITMove", stest) + } +} + func testAccITConnect(t *testing.T) { dataDBIn, err := NewMigratorDataDB(accCfgIn.DataDbType, accCfgIn.DataDbHost, accCfgIn.DataDbPort, accCfgIn.DataDbName, diff --git a/migrator/action_it_test.go b/migrator/action_it_test.go new file mode 100644 index 000000000..782d89504 --- /dev/null +++ b/migrator/action_it_test.go @@ -0,0 +1,249 @@ +// +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 migrator + +import ( + "log" + "path" + "reflect" + "testing" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + actPathIn string + actPathOut string + actCfgIn *config.CGRConfig + actCfgOut *config.CGRConfig + actMigrator *Migrator + actAction string +) + +var sTestsActIT = []func(t *testing.T){ + testActITConnect, + testActITFlush, + testActITMigrateAndMove, +} + +func TestActionITRedis(t *testing.T) { + var err error + actPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + actCfgIn, err = config.NewCGRConfigFromFolder(actPathIn) + if err != nil { + t.Fatal(err) + } + actCfgOut, err = config.NewCGRConfigFromFolder(actPathIn) + if err != nil { + t.Fatal(err) + } + actAction = utils.Migrate + for _, stest := range sTestsActIT { + t.Run("TestActionITMigrateRedis", stest) + } +} + +func TestActionITMongo(t *testing.T) { + var err error + actPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + actCfgIn, err = config.NewCGRConfigFromFolder(actPathIn) + if err != nil { + t.Fatal(err) + } + actCfgOut, err = config.NewCGRConfigFromFolder(actPathIn) + if err != nil { + t.Fatal(err) + } + actAction = utils.Migrate + for _, stest := range sTestsActIT { + t.Run("TestActionITMigrateMongo", stest) + } +} + +func TestActionITMove(t *testing.T) { + var err error + actPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + actCfgIn, err = config.NewCGRConfigFromFolder(actPathIn) + if err != nil { + t.Fatal(err) + } + actPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + actCfgOut, err = config.NewCGRConfigFromFolder(actPathOut) + if err != nil { + t.Fatal(err) + } + actAction = utils.Move + for _, stest := range sTestsActIT { + t.Run("TestActionITMove", stest) + } +} + +func TestActionITMoveEncoding(t *testing.T) { + var err error + actPathIn = path.Join(*dataDir, "conf", "samples", "tutmongojson") + actCfgIn, err = config.NewCGRConfigFromFolder(actPathIn) + if err != nil { + t.Fatal(err) + } + actPathOut = path.Join(*dataDir, "conf", "samples", "tutmongomsgpack") + actCfgOut, err = config.NewCGRConfigFromFolder(actPathOut) + if err != nil { + t.Fatal(err) + } + actAction = utils.Move + for _, stest := range sTestsActIT { + t.Run("TestActionITMoveEncoding", stest) + } +} + +/* +func TestActionITMoveEncoding2(t *testing.T) { + var err error + actPathIn = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + actCfgIn, err = config.NewCGRConfigFromFolder(actPathIn) + if err != nil { + t.Fatal(err) + } + actPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqlmsgpack") + actCfgOut, err = config.NewCGRConfigFromFolder(actPathOut) + if err != nil { + t.Fatal(err) + } + actAction = utils.Move + for _, stest := range sTestsActIT { + t.Run("TestActionITMoveEncoding2", stest) + } +}*/ + +func testActITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(actCfgIn.DataDbType, + actCfgIn.DataDbHost, actCfgIn.DataDbPort, actCfgIn.DataDbName, + actCfgIn.DataDbUser, actCfgIn.DataDbPass, actCfgIn.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(actCfgOut.DataDbType, + actCfgOut.DataDbHost, actCfgOut.DataDbPort, actCfgOut.DataDbName, + actCfgOut.DataDbUser, actCfgOut.DataDbPass, actCfgOut.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + actMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testActITFlush(t *testing.T) { + actMigrator.dmOut.DataManager().DataDB().Flush("") + if err := engine.SetDBVersions(actMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testActITMigrateAndMove(t *testing.T) { + timingSlice := []*engine.RITiming{ + &engine.RITiming{ + Years: utils.Years{}, + Months: utils.Months{}, + MonthDays: utils.MonthDays{}, + WeekDays: utils.WeekDays{}, + }, + } + + v1act := &v1Action{ + Id: "test", + ActionType: "", + BalanceType: "", + Direction: "INBOUND", + ExtraParameters: "", + ExpirationString: "", + Balance: &v1Balance{ + Timings: timingSlice, + }, + } + + v1acts := &v1Actions{ + v1act, + } + + act := &engine.Actions{ + &engine.Action{ + Id: "test", + ActionType: "", + ExtraParameters: "", + ExpirationString: "", + Weight: 0.00, + Balance: &engine.BalanceFilter{ + Timings: timingSlice, + }, + }, + } + switch actAction { + case utils.Migrate: + err := actMigrator.dmIN.setV1Actions(v1acts) + if err != nil { + t.Error("Error when setting v1 Actions ", err.Error()) + } + currentVersion := engine.Versions{utils.StatS: 2, utils.Thresholds: 2, utils.Accounts: 2, utils.Actions: 1, utils.ActionTriggers: 2, utils.ActionPlans: 2, utils.SharedGroups: 2} + err = actMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for Actions ", err.Error()) + } + err, _ = actMigrator.Migrate([]string{utils.MetaActions}) + if err != nil { + t.Error("Error when migrating Actions ", err.Error()) + } + result, err := actMigrator.dmOut.DataManager().GetActions(v1act.Id, true, utils.NonTransactional) + if err != nil { + t.Error("Error when getting Actions ", err.Error()) + } + if !reflect.DeepEqual(act, &result) { + t.Errorf("Expecting: %+v, received: %+v", act, &result) + } + case utils.Move: + if err := actMigrator.dmIN.DataManager().SetActions(v1act.Id, *act, utils.NonTransactional); err != nil { + t.Error("Error when setting ActionPlan ", err.Error()) + } + currentVersion := engine.CurrentDataDBVersions() + err := actMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for Actions ", err.Error()) + } + err, _ = actMigrator.Migrate([]string{utils.MetaActions}) + if err != nil { + t.Error("Error when migrating Actions ", err.Error()) + } + result, err := actMigrator.dmOut.DataManager().GetActions(v1act.Id, true, utils.NonTransactional) + if err != nil { + t.Error("Error when getting Actions ", err.Error()) + } + if !reflect.DeepEqual(act, &result) { + t.Errorf("Expecting: %+v, received: %+v", act, &result) + } + } +} diff --git a/migrator/action_plan_it_test.go b/migrator/action_plan_it_test.go new file mode 100644 index 000000000..a0dc2d22a --- /dev/null +++ b/migrator/action_plan_it_test.go @@ -0,0 +1,250 @@ +// +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 migrator + +import ( + "log" + "path" + "reflect" + "testing" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + actPlnPathIn string + actPlnPathOut string + actPlnCfgIn *config.CGRConfig + actPlnCfgOut *config.CGRConfig + actPlnMigrator *Migrator + actActionPlan string +) + +var sTestsActPlnIT = []func(t *testing.T){ + testActPlnITConnect, + testActPlnITFlush, + testActPlnITMigrateAndMove, +} + +func TestActionPlanITRedis(t *testing.T) { + var err error + actPlnPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + actPlnCfgIn, err = config.NewCGRConfigFromFolder(actPlnPathIn) + if err != nil { + t.Fatal(err) + } + actPlnCfgOut, err = config.NewCGRConfigFromFolder(actPlnPathIn) + if err != nil { + t.Fatal(err) + } + actActionPlan = utils.Migrate + for _, stest := range sTestsActPlnIT { + t.Run("TestActionPlanITMigrateRedis", stest) + } +} + +func TestActionPlanITMongo(t *testing.T) { + var err error + actPlnPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + actPlnCfgIn, err = config.NewCGRConfigFromFolder(actPlnPathIn) + if err != nil { + t.Fatal(err) + } + actPlnCfgOut, err = config.NewCGRConfigFromFolder(actPlnPathIn) + if err != nil { + t.Fatal(err) + } + actActionPlan = utils.Migrate + for _, stest := range sTestsActPlnIT { + t.Run("TestActionPlanITMigrateMongo", stest) + } +} + +func TestActionPlanITMove(t *testing.T) { + var err error + actPlnPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + actPlnCfgIn, err = config.NewCGRConfigFromFolder(actPlnPathIn) + if err != nil { + t.Fatal(err) + } + actPlnPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + actPlnCfgOut, err = config.NewCGRConfigFromFolder(actPlnPathOut) + if err != nil { + t.Fatal(err) + } + actActionPlan = utils.Move + for _, stest := range sTestsActPlnIT { + t.Run("TestActionPlanITMove", stest) + } +} + +func TestActionPlanITMoveEncoding(t *testing.T) { + var err error + actPlnPathIn = path.Join(*dataDir, "conf", "samples", "tutmongojson") + actPlnCfgIn, err = config.NewCGRConfigFromFolder(actPlnPathIn) + if err != nil { + t.Fatal(err) + } + actPlnPathOut = path.Join(*dataDir, "conf", "samples", "tutmongomsgpack") + actPlnCfgOut, err = config.NewCGRConfigFromFolder(actPlnPathOut) + if err != nil { + t.Fatal(err) + } + actActionPlan = utils.Move + for _, stest := range sTestsActPlnIT { + t.Run("TestActionPlanITMoveEncoding", stest) + } +} + +func TestActionPlanITMoveEncoding2(t *testing.T) { + var err error + actPlnPathIn = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + actPlnCfgIn, err = config.NewCGRConfigFromFolder(actPlnPathIn) + if err != nil { + t.Fatal(err) + } + actPlnPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqlmsgpack") + actPlnCfgOut, err = config.NewCGRConfigFromFolder(actPlnPathOut) + if err != nil { + t.Fatal(err) + } + actActionPlan = utils.Move + for _, stest := range sTestsActPlnIT { + t.Run("TestActionPlanITMoveEncoding2", stest) + } +} + +func testActPlnITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(actPlnCfgIn.DataDbType, + actPlnCfgIn.DataDbHost, actPlnCfgIn.DataDbPort, actPlnCfgIn.DataDbName, + actPlnCfgIn.DataDbUser, actPlnCfgIn.DataDbPass, actPlnCfgIn.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(actPlnCfgOut.DataDbType, + actPlnCfgOut.DataDbHost, actPlnCfgOut.DataDbPort, actPlnCfgOut.DataDbName, + actPlnCfgOut.DataDbUser, actPlnCfgOut.DataDbPass, actPlnCfgOut.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + actPlnMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testActPlnITFlush(t *testing.T) { + actPlnMigrator.dmOut.DataManager().DataDB().Flush("") + if err := engine.SetDBVersions(actPlnMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testActPlnITMigrateAndMove(t *testing.T) { + timingSlice := &engine.RITiming{ + Years: utils.Years{}, + Months: utils.Months{}, + MonthDays: utils.MonthDays{}, + WeekDays: utils.WeekDays{}, + } + + v1actPln := &v1ActionPlans{ + &v1ActionPlan{ + Id: "test", + AccountIds: []string{"one"}, + Timing: &engine.RateInterval{ + Timing: timingSlice, + }, + }, + } + + actPln := &engine.ActionPlan{ + Id: "test", + AccountIDs: utils.StringMap{"one": true}, + ActionTimings: []*engine.ActionTiming{ + &engine.ActionTiming{ + Timing: &engine.RateInterval{ + Timing: timingSlice, + }, + }, + }, + } + + switch actActionPlan { + case utils.Migrate: + err := actPlnMigrator.dmIN.setV1ActionPlans(v1actPln) + if err != nil { + t.Error("Error when setting v1 ActionPlan ", err.Error()) + } + currentVersion := engine.Versions{utils.StatS: 2, utils.Thresholds: 2, utils.Accounts: 2, utils.Actions: 2, utils.ActionTriggers: 2, utils.ActionPlans: 1, utils.SharedGroups: 2} + err = actPlnMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for ActionPlan ", err.Error()) + } + err, _ = actPlnMigrator.Migrate([]string{utils.MetaActionPlans}) + if err != nil { + t.Error("Error when migrating ActionPlan ", err.Error()) + } + result, err := actPlnMigrator.dmOut.DataManager().DataDB().GetActionPlan((*v1actPln)[0].Id, true, utils.NonTransactional) + if err != nil { + t.Error("Error when getting ActionPlan ", err.Error()) + } + // compared fields, uuid is generated in ActionTiming + if !reflect.DeepEqual(actPln.Id, result.Id) { + t.Errorf("Expecting: %+v, received: %+v", actPln.Id, result.Id) + } else if !reflect.DeepEqual(actPln.AccountIDs, result.AccountIDs) { + t.Errorf("Expecting: %+v, received: %+v", actPln.AccountIDs, result.AccountIDs) + } else if !reflect.DeepEqual(actPln.ActionTimings[0].Timing, result.ActionTimings[0].Timing) { + t.Errorf("Expecting: %+v, received: %+v", actPln.ActionTimings[0].Timing, result.ActionTimings[0].Timing) + } + case utils.Move: + if err := actPlnMigrator.dmIN.DataManager().DataDB().SetActionPlan((*v1actPln)[0].Id, actPln, true, utils.NonTransactional); err != nil { + t.Error("Error when setting ActionPlan ", err.Error()) + } + currentVersion := engine.CurrentDataDBVersions() + err := actPlnMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for ActionPlan ", err.Error()) + } + err, _ = actPlnMigrator.Migrate([]string{utils.MetaActionPlans}) + if err != nil { + t.Error("Error when migrating ActionPlan ", err.Error()) + } + result, err := actPlnMigrator.dmOut.DataManager().DataDB().GetActionPlan((*v1actPln)[0].Id, true, utils.NonTransactional) + if err != nil { + t.Error("Error when getting ActionPlan ", err.Error()) + } + // compared fields, uuid is generated in ActionTiming + if !reflect.DeepEqual(actPln.Id, result.Id) { + t.Errorf("Expecting: %+v, received: %+v", actPln.Id, result.Id) + } else if !reflect.DeepEqual(actPln.AccountIDs, result.AccountIDs) { + t.Errorf("Expecting: %+v, received: %+v", actPln.AccountIDs, result.AccountIDs) + } else if !reflect.DeepEqual(actPln.ActionTimings[0].Timing, result.ActionTimings[0].Timing) { + t.Errorf("Expecting: %+v, received: %+v", actPln.ActionTimings[0].Timing, result.ActionTimings[0].Timing) + } + } +} diff --git a/migrator/action_trigger_it_test.go b/migrator/action_trigger_it_test.go new file mode 100644 index 000000000..7c7179776 --- /dev/null +++ b/migrator/action_trigger_it_test.go @@ -0,0 +1,248 @@ +// +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 migrator + +/* +import ( + //"flag" + "log" + "path" + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + actTrgPathIn string + actTrgPathOut string + actTrgCfgIn *config.CGRConfig + actTrgCfgOut *config.CGRConfig + actTrgMigrator *Migrator + actActionTrigger string +) + +var sTestsActTrgIT = []func(t *testing.T){ + testActTrgITConnect, + testActTrgITFlush, + testActTrgITMigrateAndMove, +} + +func TestActionTriggerITRedis(t *testing.T) { + var err error + actTrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + actTrgCfgIn, err = config.NewCGRConfigFromFolder(actTrgPathIn) + if err != nil { + t.Fatal(err) + } + actTrgCfgOut, err = config.NewCGRConfigFromFolder(actTrgPathIn) + if err != nil { + t.Fatal(err) + } + actActionTrigger = utils.Migrate + for _, stest := range sTestsActTrgIT { + t.Run("TestActionTriggerITMigrateRedis", stest) + } +} + +func TestActionTriggerITMongo(t *testing.T) { + var err error + actTrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + actTrgCfgIn, err = config.NewCGRConfigFromFolder(actTrgPathIn) + if err != nil { + t.Fatal(err) + } + actTrgCfgOut, err = config.NewCGRConfigFromFolder(actTrgPathIn) + if err != nil { + t.Fatal(err) + } + actActionTrigger = utils.Migrate + for _, stest := range sTestsActTrgIT { + t.Run("TestActionTriggerITMigrateMongo", stest) + } +} + +func TestActionTriggerITMove(t *testing.T) { + var err error + actTrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + actTrgCfgIn, err = config.NewCGRConfigFromFolder(actTrgPathIn) + if err != nil { + t.Fatal(err) + } + actTrgPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + actTrgCfgOut, err = config.NewCGRConfigFromFolder(actTrgPathOut) + if err != nil { + t.Fatal(err) + } + actActionTrigger = utils.Move + for _, stest := range sTestsActTrgIT { + t.Run("TestActionTriggerITMove", stest) + } +} + +func TestActionTriggerITMoveEncoding(t *testing.T) { + var err error + actTrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmongojson") + actTrgCfgIn, err = config.NewCGRConfigFromFolder(actTrgPathIn) + if err != nil { + t.Fatal(err) + } + actTrgPathOut = path.Join(*dataDir, "conf", "samples", "tutmongomsgpack") + actTrgCfgOut, err = config.NewCGRConfigFromFolder(actTrgPathOut) + if err != nil { + t.Fatal(err) + } + actActionTrigger = utils.Move + for _, stest := range sTestsActTrgIT { + t.Run("TestActionTriggerITMoveEncoding", stest) + } +} + +func TestActionTriggerITMoveEncoding2(t *testing.T) { + var err error + actTrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + actTrgCfgIn, err = config.NewCGRConfigFromFolder(actTrgPathIn) + if err != nil { + t.Fatal(err) + } + actTrgPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqlmsgpack") + actTrgCfgOut, err = config.NewCGRConfigFromFolder(actTrgPathOut) + if err != nil { + t.Fatal(err) + } + actActionTrigger = utils.Move + for _, stest := range sTestsActTrgIT { + t.Run("TestActionTriggerITMoveEncoding2", stest) + } +} + +func testActTrgITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(actTrgCfgIn.DataDbType, + actTrgCfgIn.DataDbHost, actTrgCfgIn.DataDbPort, actTrgCfgIn.DataDbName, + actTrgCfgIn.DataDbUser, actTrgCfgIn.DataDbPass, actTrgCfgIn.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(actTrgCfgOut.DataDbType, + actTrgCfgOut.DataDbHost, actTrgCfgOut.DataDbPort, actTrgCfgOut.DataDbName, + actTrgCfgOut.DataDbUser, actTrgCfgOut.DataDbPass, actTrgCfgOut.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + actTrgMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testActTrgITFlush(t *testing.T) { + actTrgMigrator.dmOut.DataManager().DataDB().Flush("") + if err := engine.SetDBVersions(actTrgMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testActTrgITMigrateAndMove(t *testing.T) { + tim := time.Date(2012, time.February, 27, 23, 59, 59, 0, time.UTC) + v1actTrg := &v1ActionTriggers{ + &v1ActionTrigger{ + Id: "Test", + BalanceType: "*monetary", + BalanceDirection: "*out", + ThresholdType: "*max_balance", + ThresholdValue: 2, + ActionsId: "TEST_ACTIONS", + Executed: true, + BalanceExpirationDate: tim, + }, + } + actTrg := engine.ActionTriggers{ + &engine.ActionTrigger{ + ID: "Test", + Balance: &engine.BalanceFilter{ + Timings: []*engine.RITiming{}, + ExpirationDate: utils.TimePointer(tim), + Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), + }, + ExpirationDate: tim, + LastExecutionTime: tim, + ActivationDate: tim, + ThresholdType: utils.TRIGGER_MAX_BALANCE, + ThresholdValue: 2, + ActionsID: "TEST_ACTIONS", + Executed: true, + }, + } + + switch actActionTrigger { + case utils.Migrate: + err := actTrgMigrator.dmIN.setV2ActionTrigger(v1actTrg) + if err != nil { + t.Error("Error when setting v1 ActionTriggers ", err.Error()) + } + currentVersion := engine.Versions{utils.StatS: 2, utils.Thresholds: 2, utils.Accounts: 2, utils.Actions: 2, utils.ActionTriggers: 1, utils.ActionPlans: 2, utils.SharedGroups: 2} + err = actTrgMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for ActionTriggers ", err.Error()) + } + err, _ = actTrgMigrator.Migrate([]string{utils.MetaActionTriggers}) + if err != nil { + t.Error("Error when migrating ActionTriggers ", err.Error()) + } + result, err := actTrgMigrator.dmOut.DataManager().GetActionTriggers((*v1actTrg)[0].Id, false, utils.NonTransactional) + if err != nil { + t.Error("Error when getting ActionTriggers ", err.Error()) + } + if !reflect.DeepEqual(actTrg, result) { + t.Errorf("Expecting: %+v, received: %+v", actTrg, result) + } + // utils.tojson si verificat + case utils.Move: + if err := actTrgMigrator.dmIN.DataManager().SetActionTriggers((*v1actTrg)[0].Id, actTrg, utils.NonTransactional); err != nil { + t.Error("Error when setting ActionTriggers ", err.Error()) + } + currentVersion := engine.CurrentDataDBVersions() + err := actTrgMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for ActionTriggers ", err.Error()) + } + err, _ = actTrgMigrator.Migrate([]string{utils.MetaActionTriggers}) + if err != nil { + t.Error("Error when migrating ActionTriggers ", err.Error()) + } + result, err := actTrgMigrator.dmOut.DataManager().GetActionTriggers((*v1actTrg)[0].Id, false, utils.NonTransactional) + if err != nil { + t.Error("Error when getting ActionTriggers ", err.Error()) + } + if !reflect.DeepEqual(actTrg, result) { + t.Errorf("Expecting: %+v, received: %+v", actTrg, result) + } + } +} +*/ diff --git a/migrator/migratorDataDB.go b/migrator/migrator_datadb.go similarity index 100% rename from migrator/migratorDataDB.go rename to migrator/migrator_datadb.go diff --git a/migrator/migrator_it_test.go b/migrator/migrator_it_test.go index c801778c0..499be7d7d 100644 --- a/migrator/migrator_it_test.go +++ b/migrator/migrator_it_test.go @@ -69,28 +69,6 @@ var sTestsITMigrator = []func(t *testing.T){ testMigratorTimings, testMigratorThreshold, testMigratorAttributeProfile, - //TPS - testMigratorTPRatingProfile, - testMigratorTPSuppliers, - testMigratorTPActions, - testMigratorTPAccountActions, - testMigratorTpActionTriggers, - testMigratorTpActionPlans, - testMigratorTpUsers, - testMigratorTpTimings, - testMigratorTpThreshold, - testMigratorTpStats, - testMigratorTpSharedGroups, - testMigratorTpResources, - testMigratorTpRatingProfiles, - testMigratorTpRatingPlans, - testMigratorTpRates, - testMigratorTpFilter, - testMigratorTpDestination, - testMigratorTpDestinationRate, - testMigratorTpDerivedChargers, - testMigratorTpCdrStats, - testMigratorTpAliases, testFlush, } @@ -1780,1113 +1758,4 @@ func testMigratorAttributeProfile(t *testing.T) { } } } - -//TP TESTS -func testMigratorTPRatingProfile(t *testing.T) { - tpRatingProfile := []*utils.TPRatingProfile{ - &utils.TPRatingProfile{ - TPid: "TPRProf1", - LoadId: "RPrf", - Direction: "*out", - Tenant: "Tenant1", - Category: "Category", - Subject: "Subject", - RatingPlanActivations: []*utils.TPRatingActivation{ - &utils.TPRatingActivation{ - ActivationTime: "2014-07-29T15:00:00Z", - RatingPlanId: "PlanOne", - FallbackSubjects: "FallBack", - CdrStatQueueIds: "RandomId", - }, - &utils.TPRatingActivation{ - ActivationTime: "2015-07-29T10:00:00Z", - RatingPlanId: "PlanTwo", - FallbackSubjects: "FallOut", - CdrStatQueueIds: "RandomIdTwo", - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPRatingProfiles(tpRatingProfile); err != nil { - t.Error("Error when setting Stats ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for stats ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpRatingProfiles}) - if err != nil { - t.Error("Error when migrating Stats ", err.Error()) - } - result, err := mig.OutStorDB().GetTPRatingProfiles(tpRatingProfile[0]) - if err != nil { - t.Error("Error when getting Stats ", err.Error()) - } - if !reflect.DeepEqual(tpRatingProfile[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpRatingProfile[0], result[0]) - } - } -} - -func testMigratorTPSuppliers(t *testing.T) { - tpSplPr := []*utils.TPSupplierProfile{ - &utils.TPSupplierProfile{ - TPid: "SupplierTPID12", - Tenant: "cgrates.org", - ID: "SUPL_1", - FilterIDs: []string{"FLTR_ACNT_dan"}, - ActivationInterval: &utils.TPActivationInterval{ - ActivationTime: "2014-07-29T15:00:00Z", - ExpiryTime: "", - }, - Sorting: "*lowest_cost", - SortingParameters: []string{"Parameter1"}, - Suppliers: []*utils.TPSupplier{ - &utils.TPSupplier{ - ID: "supplier1", - AccountIDs: []string{"Account1"}, - FilterIDs: []string{"FLTR_1"}, - RatingPlanIDs: []string{"RPL_1"}, - ResourceIDs: []string{"ResGroup1"}, - StatIDs: []string{"Stat1"}, - Weight: 10, - Blocker: false, - }, - }, - Weight: 20, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPSuppliers(tpSplPr); err != nil { - t.Error("Error when setting TpSupplier ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpSupplier ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpSuppliers}) - if err != nil { - t.Error("Error when migrating TpSupplier ", err.Error()) - } - result, err := mig.OutStorDB().GetTPSuppliers(tpSplPr[0].TPid, tpSplPr[0].ID) - if err != nil { - t.Error("Error when getting TPSupplier ", err.Error()) - } else if !reflect.DeepEqual(tpSplPr, result) { - t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(tpSplPr), utils.ToJSON(result)) - } - } -} - -func testMigratorTPActions(t *testing.T) { - tpActions := []*utils.TPActions{ - &utils.TPActions{ - TPid: "TPAcc", - ID: "ID", - Actions: []*utils.TPAction{ - &utils.TPAction{ - Identifier: "*topup_reset", - BalanceId: "BalID", - BalanceType: "*data", - Directions: "*out", - Units: "10", - ExpiryTime: "*unlimited", - Filter: "", - TimingTags: "2014-01-14T00:00:00Z", - DestinationIds: "DST_1002", - RatingSubject: "SPECIAL_1002", - Categories: "", - SharedGroups: "SHARED_A", - BalanceWeight: "10", - ExtraParameters: "", - BalanceBlocker: "false", - BalanceDisabled: "false", - Weight: 10, - }, - &utils.TPAction{ - Identifier: "*log", - BalanceId: "BalID", - BalanceType: "*monetary", - Directions: "*out", - Units: "120", - ExpiryTime: "*unlimited", - Filter: "", - TimingTags: "2014-01-14T00:00:00Z", - DestinationIds: "*any", - RatingSubject: "SPECIAL_1002", - Categories: "", - SharedGroups: "SHARED_A", - BalanceWeight: "11", - ExtraParameters: "", - BalanceBlocker: "false", - BalanceDisabled: "false", - Weight: 11, - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPActions(tpActions); err != nil { - t.Error("Error when setting TpActions ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpActions ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpActions}) - if err != nil { - t.Error("Error when migrating TpActions ", err.Error()) - } - result, err := mig.OutStorDB().GetTPActions(tpActions[0].TPid, tpActions[0].ID) - if err != nil { - t.Error("Error when getting TpActions ", err.Error()) - } - if !reflect.DeepEqual(tpActions[0].TPid, result[0].TPid) { - t.Errorf("Expecting: %+v, received: %+v", tpActions[0].TPid, result[0].TPid) - } else if !reflect.DeepEqual(tpActions[0].ID, result[0].ID) { - t.Errorf("Expecting: %+v, received: %+v", tpActions[0].ID, result[0].ID) - } else if !reflect.DeepEqual(tpActions[0].Actions[0], result[0].Actions[0]) && - !reflect.DeepEqual(tpActions[0].Actions[0], result[0].Actions[1]) { - t.Errorf("Expecting: %+v, received: %+v", tpActions[0].Actions[0], result[0].Actions[0]) - } else if !reflect.DeepEqual(tpActions[0].Actions[1], result[0].Actions[1]) && - !reflect.DeepEqual(tpActions[0].Actions[1], result[0].Actions[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpActions[0].Actions[1], result[0].Actions[1]) - } - } -} - -func testMigratorTPAccountActions(t *testing.T) { - tpAccActions := []*utils.TPAccountActions{ - &utils.TPAccountActions{ - TPid: "TPAcc", - LoadId: "ID", - Tenant: "cgrates.org", - Account: "1001", - ActionPlanId: "PREPAID_10", - ActionTriggersId: "STANDARD_TRIGGERS", - AllowNegative: true, - Disabled: false, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPAccountActions(tpAccActions); err != nil { - t.Error("Error when setting TpAccountActions ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpAccountActions ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpAccountActions}) - if err != nil { - t.Error("Error when migrating TpAccountActions ", err.Error()) - } - result, err := mig.OutStorDB().GetTPAccountActions(&utils.TPAccountActions{TPid: "TPAcc"}) - if err != nil { - t.Error("Error when getting TpAccountActions ", err.Error()) - } - if !reflect.DeepEqual(tpAccActions[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpAccActions[0], result[0]) - } - } -} - -func testMigratorTpActionTriggers(t *testing.T) { - tpActionTriggers := []*utils.TPActionTriggers{ - &utils.TPActionTriggers{ - TPid: "TPAct", - ID: "STANDARD_TRIGGERS", - ActionTriggers: []*utils.TPActionTrigger{ - &utils.TPActionTrigger{ - Id: "STANDARD_TRIGGERS", - UniqueID: "", - ThresholdType: "*min_balance", - ThresholdValue: 2, - Recurrent: false, - MinSleep: "0", - ExpirationDate: "", - ActivationDate: "", - BalanceId: "", - BalanceType: "*monetary", - BalanceDirections: "*out", - BalanceDestinationIds: "FS_USERS", - BalanceWeight: "", - BalanceExpirationDate: "", - BalanceTimingTags: "", - BalanceRatingSubject: "", - BalanceCategories: "", - BalanceSharedGroups: "", - BalanceBlocker: "", - BalanceDisabled: "", - MinQueuedItems: 3, - ActionsId: "LOG_WARNING", - Weight: 10, - }, - &utils.TPActionTrigger{ - Id: "STANDARD_TRIGGERS", - UniqueID: "", - ThresholdType: "*max_event_counter", - ThresholdValue: 5, - Recurrent: false, - MinSleep: "0", - ExpirationDate: "", - ActivationDate: "", - BalanceId: "", - BalanceType: "*monetary", - BalanceDirections: "*out", - BalanceDestinationIds: "FS_USERS", - BalanceWeight: "", - BalanceExpirationDate: "", - BalanceTimingTags: "", - BalanceRatingSubject: "", - BalanceCategories: "", - BalanceSharedGroups: "", - BalanceBlocker: "", - BalanceDisabled: "", - MinQueuedItems: 3, - ActionsId: "LOG_WARNING", - Weight: 10, - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPActionTriggers(tpActionTriggers); err != nil { - t.Error("Error when setting TpActionTriggers ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpActionTriggers ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpActionTriggers}) - if err != nil { - t.Error("Error when migrating TpActionTriggers ", err.Error()) - } - result, err := mig.OutStorDB().GetTPActionTriggers(tpActionTriggers[0].TPid, tpActionTriggers[0].ID) - if err != nil { - t.Error("Error when getting TpAccountActions ", err.Error()) - } - if !reflect.DeepEqual(tpActionTriggers[0].TPid, result[0].TPid) { - t.Errorf("Expecting: %+v, received: %+v", tpActionTriggers[0].TPid, result[0].TPid) - } else if !reflect.DeepEqual(tpActionTriggers[0].ID, result[0].ID) { - t.Errorf("Expecting: %+v, received: %+v", tpActionTriggers[0].ID, result[0].ID) - } else if !reflect.DeepEqual(tpActionTriggers[0].ActionTriggers[0], result[0].ActionTriggers[0]) && - !reflect.DeepEqual(tpActionTriggers[0].ActionTriggers[0], result[0].ActionTriggers[1]) { - t.Errorf("Expecting: %+v, received: %+v", tpActionTriggers[0].ActionTriggers[0], result[0].ActionTriggers[0]) - } else if !reflect.DeepEqual(tpActionTriggers[0].ActionTriggers[1], result[0].ActionTriggers[1]) && - !reflect.DeepEqual(tpActionTriggers[0].ActionTriggers[1], result[0].ActionTriggers[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpActionTriggers[0].ActionTriggers[1], result[0].ActionTriggers[1]) - } - } -} - -func testMigratorTpActionPlans(t *testing.T) { - tpAccPlan := []*utils.TPActionPlan{ - &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, - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPActionPlans(tpAccPlan); err != nil { - t.Error("Error when setting TpActionPlans ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpActionPlans ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpActionPlans}) - if err != nil { - t.Error("Error when migrating TpActionPlans ", err.Error()) - } - result, err := mig.OutStorDB().GetTPActionPlans(tpAccPlan[0].TPid, tpAccPlan[0].ID) - if err != nil { - t.Error("Error when getting TpActionPlans ", err.Error()) - } - if !reflect.DeepEqual(tpAccPlan[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpAccPlan[0], result[0]) - } - } -} - -func testMigratorTpUsers(t *testing.T) { - tpUser := []*utils.TPUsers{ - &utils.TPUsers{ - TPid: "TPU1", - UserName: "User1", - Tenant: "Tenant1", - Masked: true, - Weight: 20, - Profile: []*utils.TPUserProfile{ - &utils.TPUserProfile{ - AttrName: "UserProfile1", - AttrValue: "ValUP1", - }, - &utils.TPUserProfile{ - AttrName: "UserProfile2", - AttrValue: "ValUP2", - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPUsers(tpUser); err != nil { - t.Error("Error when setting TpUsers ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpUsers ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpUsers}) - if err != nil { - t.Error("Error when migrating TpUsers ", err.Error()) - } - result, err := mig.OutStorDB().GetTPUsers(&utils.TPUsers{TPid: tpUser[0].TPid}) - if err != nil { - t.Error("Error when getting TpUsers ", err.Error()) - } - if !reflect.DeepEqual(tpUser[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpUser[0], result[0]) - } - } -} - -func testMigratorTpTimings(t *testing.T) { - tpTiming := []*utils.ApierTPTiming{&utils.ApierTPTiming{ - TPid: "TPT1", - ID: "Timing", - Years: "2017", - Months: "05", - MonthDays: "01", - WeekDays: "1", - Time: "15:00:00Z", - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPTimings(tpTiming); err != nil { - t.Error("Error when setting TpTiming ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpTiming ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpTiming}) - if err != nil { - t.Error("Error when migrating TpTiming ", err.Error()) - } - result, err := mig.OutStorDB().GetTPTimings(tpTiming[0].TPid, tpTiming[0].ID) - if err != nil { - t.Error("Error when getting TpTiming ", err.Error()) - } - if !reflect.DeepEqual(tpTiming[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpTiming[0], result[0]) - } - } -} - -func testMigratorTpThreshold(t *testing.T) { - tpThreshold := []*utils.TPThreshold{ - &utils.TPThreshold{ - TPid: "TH1", - Tenant: "cgrates.org", - ID: "Threhold", - FilterIDs: []string{"FLTR_1", "FLTR_2"}, - ActivationInterval: &utils.TPActivationInterval{ - ActivationTime: "2014-07-29T15:00:00Z", - ExpiryTime: "", - }, - Recurrent: true, - MinSleep: "1s", - Blocker: true, - Weight: 10, - ActionIDs: []string{"Thresh1", "Thresh2"}, - Async: true, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPThresholds(tpThreshold); err != nil { - t.Error("Error when setting TpThreshold ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpThreshold ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpThresholds}) - if err != nil { - t.Error("Error when migrating TpThreshold ", err.Error()) - } - result, err := mig.OutStorDB().GetTPThresholds(tpThreshold[0].TPid, tpThreshold[0].ID) - if err != nil { - t.Error("Error when getting TpThreshold ", err.Error()) - } - if !reflect.DeepEqual(tpThreshold[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpThreshold[0], result[0]) - } - } -} - -func testMigratorTpStats(t *testing.T) { - tpStat := []*utils.TPStats{ - &utils.TPStats{ - Tenant: "cgrates.org", - TPid: "TPS1", - ID: "Stat1", - FilterIDs: []string{"FLTR_1"}, - ActivationInterval: &utils.TPActivationInterval{ - ActivationTime: "2014-07-29T15:00:00Z", - ExpiryTime: "", - }, - TTL: "1", - Metrics: []*utils.MetricWithParams{ - &utils.MetricWithParams{MetricID: "MetricValue", Parameters: ""}, - &utils.MetricWithParams{MetricID: "MetricValueTwo", Parameters: ""}, - }, - Blocker: false, - Stored: false, - Weight: 20, - MinItems: 1, - ThresholdIDs: []string{"ThreshValue", "ThreshValueTwo"}, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPStats(tpStat); err != nil { - t.Error("Error when setting TpStats ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpStats ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpStats}) - if err != nil { - t.Error("Error when migrating TpStats ", err.Error()) - } - result, err := mig.OutStorDB().GetTPStats(tpStat[0].TPid, tpStat[0].ID) - if err != nil { - t.Error("Error when getting TpStats ", err.Error()) - } - if !reflect.DeepEqual(tpStat[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpStat[0], result[0]) - } - } -} - -func testMigratorTpSharedGroups(t *testing.T) { - tpSharedGroups := []*utils.TPSharedGroups{ - &utils.TPSharedGroups{ - TPid: "Tpi", - ID: "TpSg", - SharedGroups: []*utils.TPSharedGroup{ - &utils.TPSharedGroup{ - Account: "AccOne", - Strategy: "StrategyOne", - RatingSubject: "SubOne", - }, - &utils.TPSharedGroup{ - Account: "AccTow", - Strategy: "StrategyTwo", - RatingSubject: "SubTwo", - }, - &utils.TPSharedGroup{ - Account: "AccPlus", - Strategy: "StrategyPlus", - RatingSubject: "SubPlus", - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPSharedGroups(tpSharedGroups); err != nil { - t.Error("Error when setting TpSharedGroups ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpSharedGroups ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpSharedGroups}) - if err != nil { - t.Error("Error when migrating TpSharedGroups ", err.Error()) - } - result, err := mig.OutStorDB().GetTPSharedGroups(tpSharedGroups[0].TPid, tpSharedGroups[0].ID) - if err != nil { - t.Error("Error when getting TpSharedGroups ", err.Error()) - } - if !reflect.DeepEqual(tpSharedGroups[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpSharedGroups[0], result[0]) - } - } -} - -func testMigratorTpResources(t *testing.T) { - tpRes := []*utils.TPResource{ - &utils.TPResource{ - Tenant: "cgrates.org", - TPid: "TPR1", - ID: "ResGroup1", - FilterIDs: []string{"FLTR_1"}, - ActivationInterval: &utils.TPActivationInterval{ - ActivationTime: "2014-07-29T15:00:00Z", - ExpiryTime: "", - }, - UsageTTL: "1s", - Limit: "7", - AllocationMessage: "", - Blocker: true, - Stored: true, - Weight: 20, - ThresholdIDs: []string{"ValOne", "ValTwo"}, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPResources(tpRes); err != nil { - t.Error("Error when setting TpResources ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpResources ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpResources}) - if err != nil { - t.Error("Error when migrating TpResources ", err.Error()) - } - result, err := mig.OutStorDB().GetTPResources(tpRes[0].TPid, tpRes[0].ID) - if err != nil { - t.Error("Error when getting TpResources ", err.Error()) - } - if !reflect.DeepEqual(tpRes[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpRes[0], result[0]) - } - } -} - -func testMigratorTpRatingProfiles(t *testing.T) { - tpRatingProfile := []*utils.TPRatingProfile{ - &utils.TPRatingProfile{ - TPid: "TPRProf1", - LoadId: "RPrf", - Direction: "*out", - Tenant: "Tenant1", - Category: "Category", - Subject: "Subject", - RatingPlanActivations: []*utils.TPRatingActivation{ - &utils.TPRatingActivation{ - ActivationTime: "2014-07-29T15:00:00Z", - RatingPlanId: "PlanOne", - FallbackSubjects: "FallBack", - CdrStatQueueIds: "RandomId", - }, - &utils.TPRatingActivation{ - ActivationTime: "2015-07-29T10:00:00Z", - RatingPlanId: "PlanTwo", - FallbackSubjects: "FallOut", - CdrStatQueueIds: "RandomIdTwo", - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPRatingProfiles(tpRatingProfile); err != nil { - t.Error("Error when setting TpRatingProfiles ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpRatingProfiles ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpRatingProfiles}) - if err != nil { - t.Error("Error when migrating TpRatingProfiles ", err.Error()) - } - result, err := mig.OutStorDB().GetTPRatingProfiles(&utils.TPRatingProfile{TPid: tpRatingProfile[0].TPid}) - if err != nil { - t.Error("Error when getting TpRatingProfiles ", err.Error()) - } - if !reflect.DeepEqual(tpRatingProfile[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpRatingProfile[0], result[0]) - } - } -} - -func testMigratorTpRatingPlans(t *testing.T) { - tpRatingPlan := []*utils.TPRatingPlan{ - &utils.TPRatingPlan{ - TPid: "TPRP1", - ID: "Plan1", - RatingPlanBindings: []*utils.TPRatingPlanBinding{ - &utils.TPRatingPlanBinding{ - DestinationRatesId: "RateId", - TimingId: "TimingID", - Weight: 12, - }, - &utils.TPRatingPlanBinding{ - DestinationRatesId: "DR_FREESWITCH_USERS", - TimingId: "ALWAYS", - Weight: 10, - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPRatingPlans(tpRatingPlan); err != nil { - t.Error("Error when setting TpRatingPlans ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpRatingPlans ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpRatingPlans}) - if err != nil { - t.Error("Error when migrating TpRatingPlans ", err.Error()) - } - result, err := mig.OutStorDB().GetTPRatingPlans("TPRP1", "Plan1", nil) - if err != nil { - t.Error("Error when getting TpRatingPlans ", err.Error()) - } - if !reflect.DeepEqual(tpRatingPlan[0].TPid, result[0].TPid) { - t.Errorf("Expecting: %+v, received: %+v", tpRatingPlan[0].TPid, result[0].TPid) - } else if !reflect.DeepEqual(tpRatingPlan[0].ID, result[0].ID) { - t.Errorf("Expecting: %+v, received: %+v", tpRatingPlan[0].ID, result[0].ID) - } else if !reflect.DeepEqual(tpRatingPlan[0].RatingPlanBindings[0], result[0].RatingPlanBindings[0]) && - !reflect.DeepEqual(tpRatingPlan[0].RatingPlanBindings[1], result[0].RatingPlanBindings[1]) && - !reflect.DeepEqual(tpRatingPlan[0].RatingPlanBindings[1], result[0].RatingPlanBindings[0]) && - !reflect.DeepEqual(tpRatingPlan[0].RatingPlanBindings[0], result[0].RatingPlanBindings[1]) { - t.Errorf("Expecting: %+v, received: %+v", tpRatingPlan[0].RatingPlanBindings[0], result[0].RatingPlanBindings[0]) - } else if !reflect.DeepEqual(tpRatingPlan[0].RatingPlanBindings[0], result[0].RatingPlanBindings[0]) && - !reflect.DeepEqual(tpRatingPlan[0].RatingPlanBindings[1], result[0].RatingPlanBindings[1]) && - !reflect.DeepEqual(tpRatingPlan[0].RatingPlanBindings[1], result[0].RatingPlanBindings[0]) && - !reflect.DeepEqual(tpRatingPlan[0].RatingPlanBindings[0], result[0].RatingPlanBindings[1]) { - t.Errorf("Expecting: %+v, received: %+v", tpRatingPlan[0].RatingPlanBindings[1], result[0].RatingPlanBindings[1]) - } - - } -} - -func testMigratorTpRates(t *testing.T) { - tpRate := []*utils.TPRate{ - &utils.TPRate{ - TPid: "TPidTpRate", - ID: "RT_FS_USERS", - RateSlots: []*utils.RateSlot{ - &utils.RateSlot{ - ConnectFee: 12, - Rate: 3, - RateUnit: "6s", - RateIncrement: "6s", - GroupIntervalStart: "0s", - }, - &utils.RateSlot{ - ConnectFee: 12, - Rate: 3, - RateUnit: "4s", - RateIncrement: "6s", - GroupIntervalStart: "1s", - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPRates(tpRate); err != nil { - t.Error("Error when setting TpRates ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpRates ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpRates}) - if err != nil { - t.Error("Error when migrating TpRates ", err.Error()) - } - result, err := mig.OutStorDB().GetTPRates(tpRate[0].TPid, tpRate[0].ID) - if err != nil { - t.Error("Error when getting TpRates ", err.Error()) - } - if !reflect.DeepEqual(tpRate[0].TPid, result[0].TPid) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].TPid, result[0].TPid) - } else if !reflect.DeepEqual(tpRate[0].ID, result[0].ID) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].ID, result[0].ID) - } - if !reflect.DeepEqual(tpRate[0].RateSlots[0].ConnectFee, result[0].RateSlots[0].ConnectFee) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[0].ConnectFee, result[0].RateSlots[0].ConnectFee) - } else if !reflect.DeepEqual(tpRate[0].RateSlots[0].Rate, result[0].RateSlots[0].Rate) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[0].Rate, result[0].RateSlots[0].Rate) - } else if !reflect.DeepEqual(tpRate[0].RateSlots[0].RateUnit, result[0].RateSlots[0].RateUnit) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[0].RateUnit, result[0].RateSlots[0].RateUnit) - } else if !reflect.DeepEqual(tpRate[0].RateSlots[0].RateIncrement, result[0].RateSlots[0].RateIncrement) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[0].RateIncrement, result[0].RateSlots[0].RateIncrement) - } else if !reflect.DeepEqual(tpRate[0].RateSlots[0].GroupIntervalStart, result[0].RateSlots[0].GroupIntervalStart) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[0].GroupIntervalStart, result[0].RateSlots[0].GroupIntervalStart) - } - if !reflect.DeepEqual(tpRate[0].RateSlots[1].ConnectFee, result[0].RateSlots[1].ConnectFee) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[1].ConnectFee, result[0].RateSlots[1].ConnectFee) - } else if !reflect.DeepEqual(tpRate[0].RateSlots[1].Rate, result[0].RateSlots[1].Rate) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[1].Rate, result[0].RateSlots[1].Rate) - } else if !reflect.DeepEqual(tpRate[0].RateSlots[1].RateUnit, result[0].RateSlots[1].RateUnit) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[1].RateUnit, result[0].RateSlots[1].RateUnit) - } else if !reflect.DeepEqual(tpRate[0].RateSlots[1].RateIncrement, result[0].RateSlots[1].RateIncrement) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[1].RateIncrement, result[0].RateSlots[1].RateIncrement) - } else if !reflect.DeepEqual(tpRate[0].RateSlots[1].GroupIntervalStart, result[0].RateSlots[1].GroupIntervalStart) { - t.Errorf("Expecting: %+v, received: %+v", tpRate[0].RateSlots[1].GroupIntervalStart, result[0].RateSlots[1].GroupIntervalStart) - } - } -} - -func testMigratorTpFilter(t *testing.T) { - tpFilter := []*utils.TPFilterProfile{ - &utils.TPFilterProfile{ - TPid: "TP1", - Tenant: "cgrates.org", - ID: "Filter", - Filters: []*utils.TPFilter{ - &utils.TPFilter{ - Type: "*string", - FieldName: "Account", - Values: []string{"1001", "1002"}, - }, - }, - ActivationInterval: &utils.TPActivationInterval{ - ActivationTime: "2014-07-29T15:00:00Z", - ExpiryTime: "", - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPFilters(tpFilter); err != nil { - t.Error("Error when setting TpFilter ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpFilter ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpFilters}) - if err != nil { - t.Error("Error when migrating TpFilter ", err.Error()) - } - result, err := mig.OutStorDB().GetTPFilters(tpFilter[0].TPid, tpFilter[0].ID) - if err != nil { - t.Error("Error when getting TpFilter ", err.Error()) - } - if !reflect.DeepEqual(tpFilter[0].TPid, result[0].TPid) { - t.Errorf("Expecting: %+v, received: %+v", tpFilter[0].TPid, result[0].TPid) - } else if !reflect.DeepEqual(tpFilter[0].ID, result[0].ID) { - t.Errorf("Expecting: %+v, received: %+v", tpFilter[0].ID, result[0].ID) - } else if !reflect.DeepEqual(tpFilter[0].Filters, result[0].Filters) { - t.Errorf("Expecting: %+v, received: %+v", tpFilter[0].Filters, result[0].Filters) - } else if !reflect.DeepEqual(tpFilter[0].ActivationInterval, result[0].ActivationInterval) { - t.Errorf("Expecting: %+v, received: %+v", tpFilter[0].ActivationInterval, result[0].ActivationInterval) - } - } -} - -func testMigratorTpDestination(t *testing.T) { - tpDestination := []*utils.TPDestination{ - &utils.TPDestination{ - TPid: "TPD", - ID: "GERMANY", - Prefixes: []string{"+49", "+4915"}, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPDestinations(tpDestination); err != nil { - t.Error("Error when setting TpDestination ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpDestination ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpDestinations}) - if err != nil { - t.Error("Error when migrating TpDestination ", err.Error()) - } - result, err := mig.OutStorDB().GetTPDestinations(tpDestination[0].TPid, tpDestination[0].ID) - if err != nil { - t.Error("Error when getting TpDestination ", err.Error()) - } - if !reflect.DeepEqual(tpDestination[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpDestination[0], result[0]) - } - } -} - -func testMigratorTpDestinationRate(t *testing.T) { - tpDestRate := []*utils.TPDestinationRate{ - &utils.TPDestinationRate{ - TPid: "testTPid", - ID: "1", - DestinationRates: []*utils.DestinationRate{ - &utils.DestinationRate{ - DestinationId: "GERMANY", - RateId: "RT_1CENT", - RoundingMethod: "*up", - RoundingDecimals: 0, - MaxCost: 0.0, - MaxCostStrategy: "", - }, - }, - }, - } - - switch action { - case Move: - if err := mig.InStorDB().SetTPDestinationRates(tpDestRate); err != nil { - t.Error("Error when setting TpDestinationRate ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpDestinationRate ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpDestinationRates}) - if err != nil { - t.Error("Error when migrating TpDestinationRate ", err.Error()) - } //OutStorDB - result, err := mig.InStorDB().GetTPDestinationRates("testTPid", "", nil) - if err != nil { - t.Error("Error when getting TpDestinationRate ", err.Error()) - } - if !reflect.DeepEqual(tpDestRate[0].TPid, result[0].TPid) { - t.Errorf("Expecting: %+v, received: %+v", tpDestRate[0].TPid, result[0].TPid) - } else if !reflect.DeepEqual(tpDestRate[0].ID, result[0].ID) { - t.Errorf("Expecting: %+v, received: %+v", tpDestRate[0].ID, result[0].ID) - } - if !reflect.DeepEqual(tpDestRate[0].DestinationRates[0].DestinationId, result[0].DestinationRates[0].DestinationId) { - t.Errorf("Expecting: %+v, received: %+v", tpDestRate[0].DestinationRates[0].DestinationId, result[0].DestinationRates[0].DestinationId) - } else if !reflect.DeepEqual(tpDestRate[0].DestinationRates[0].RateId, result[0].DestinationRates[0].RateId) { - t.Errorf("Expecting: %+v, received: %+v", tpDestRate[0].DestinationRates[0].RateId, result[0].DestinationRates[0].RateId) - } else if !reflect.DeepEqual(tpDestRate[0].DestinationRates[0], result[0].DestinationRates[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpDestRate[0].DestinationRates[0], result[0].DestinationRates[0]) - } - } -} - -func testMigratorTpDerivedChargers(t *testing.T) { - tpDerivedChargers := []*utils.TPDerivedChargers{ - &utils.TPDerivedChargers{ - TPid: "TPD", - LoadId: "LoadID", - Direction: "*out", - Tenant: "cgrates.org", - Category: "call", - Account: "1001", - Subject: "1001", - DestinationIds: "", - DerivedChargers: []*utils.TPDerivedCharger{ - &utils.TPDerivedCharger{ - RunId: "derived_run1", - RunFilters: "", - ReqTypeField: "^*rated", - DirectionField: "*default", - TenantField: "*default", - CategoryField: "*default", - AccountField: "*default", - SubjectField: "^1002", - DestinationField: "*default", - SetupTimeField: "*default", - PddField: "*default", - AnswerTimeField: "*default", - UsageField: "*default", - SupplierField: "*default", - DisconnectCauseField: "*default", - CostField: "*default", - RatedField: "*default", - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPDerivedChargers(tpDerivedChargers); err != nil { - t.Error("Error when setting TpDerivedChargers ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpDerivedChargers ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpDerivedChargers}) - if err != nil { - t.Error("Error when migrating TpDerivedChargers ", err.Error()) - } - result, err := mig.OutStorDB().GetTPDerivedChargers(&utils.TPDerivedChargers{TPid: tpDerivedChargers[0].TPid}) - if err != nil { - t.Error("Error when getting TpDerivedChargers ", err.Error()) - } - if !reflect.DeepEqual(tpDerivedChargers[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpDerivedChargers[0], result[0]) - } - } -} - -func testMigratorTpCdrStats(t *testing.T) { - tpCdrStats := []*utils.TPCdrStats{ - &utils.TPCdrStats{ - TPid: "TPCdr", - ID: "ID", - CdrStats: []*utils.TPCdrStat{ - &utils.TPCdrStat{ - QueueLength: "10", - TimeWindow: "0", - SaveInterval: "10s", - Metrics: "ASR", - SetupInterval: "", - TORs: "", - CdrHosts: "", - CdrSources: "", - ReqTypes: "", - Directions: "", - Tenants: "cgrates.org", - Categories: "", - Accounts: "", - Subjects: "1001", - DestinationIds: "1003", - PddInterval: "", - UsageInterval: "", - Suppliers: "suppl1", - DisconnectCauses: "", - MediationRunIds: "*default", - RatedAccounts: "", - RatedSubjects: "", - CostInterval: "", - ActionTriggers: "CDRST1_WARN", - }, - &utils.TPCdrStat{ - QueueLength: "10", - TimeWindow: "0", - SaveInterval: "10s", - Metrics: "ACC", - SetupInterval: "", - TORs: "", - CdrHosts: "", - CdrSources: "", - ReqTypes: "", - Directions: "", - Tenants: "cgrates.org", - Categories: "", - Accounts: "", - Subjects: "1002", - DestinationIds: "1003", - PddInterval: "", - UsageInterval: "", - Suppliers: "suppl1", - DisconnectCauses: "", - MediationRunIds: "*default", - RatedAccounts: "", - RatedSubjects: "", - CostInterval: "", - ActionTriggers: "CDRST1_WARN", - }, - }, - }, - } - switch action { - case Move: - if err := mig.InStorDB().SetTPCdrStats(tpCdrStats); err != nil { - t.Error("Error when setting TpCdrStats ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpCdrStats ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpCdrStats}) - if err != nil { - t.Error("Error when migrating TpCdrStats ", err.Error()) - } - result, err := mig.OutStorDB().GetTPCdrStats(tpCdrStats[0].TPid, tpCdrStats[0].ID) - if err != nil { - t.Error("Error when getting TpCdrStats ", err.Error()) - } - if !reflect.DeepEqual(tpCdrStats[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpCdrStats[0], result[0]) - } - } -} - -func testMigratorTpAliases(t *testing.T) { - tpAliases := []*utils.TPAliases{ - &utils.TPAliases{ - TPid: "tpID", - Direction: "*out", - Tenant: "cgrates.org", - Category: "call", - Account: "1001", - Subject: "1002", - Context: "", - Values: []*utils.TPAliasValue{ - &utils.TPAliasValue{ - DestinationId: "1002", - Target: "1002", - Original: "1002", - Alias: "1002", - Weight: 20.0, - }, - }, - }, - } - - switch action { - case Move: - if err := mig.InStorDB().SetTPAliases(tpAliases); err != nil { - t.Error("Error when setting TpAliases ", err.Error()) - } - currentVersion := engine.CurrentStorDBVersions() - err := mig.OutStorDB().SetVersions(currentVersion, false) - if err != nil { - t.Error("Error when setting version for TpAliases ", err.Error()) - } - err, _ = mig.Migrate([]string{utils.MetaTpAliases}) - if err != nil { - t.Error("Error when migrating TpAliases ", err.Error()) - } - result, err := mig.OutStorDB().GetTPAliases(&utils.TPAliases{TPid: tpAliases[0].TPid}) - if err != nil { - t.Error("Error when getting TpAliases ", err.Error()) - } - if !reflect.DeepEqual(tpAliases[0], result[0]) { - t.Errorf("Expecting: %+v, received: %+v", tpAliases[0], result[0]) - } - } -} */ diff --git a/migrator/migratorStorDB.go b/migrator/migrator_stordb.go similarity index 91% rename from migrator/migratorStorDB.go rename to migrator/migrator_stordb.go index 8754dc779..508632220 100755 --- a/migrator/migratorStorDB.go +++ b/migrator/migrator_stordb.go @@ -25,6 +25,8 @@ import ( type MigratorStorDB interface { getV1CDR() (v1Cdr *v1Cdrs, err error) setV1CDR(v1Cdr *v1Cdrs) (err error) + createV1SMCosts() (err error) + renameV1SMCosts() (err error) getV2SMCost() (v2Cost *v2SessionsCost, err error) setV2SMCost(v2Cost *v2SessionsCost) (err error) remV2SMCost(v2Cost *v2SessionsCost) (err error) diff --git a/migrator/v1migrator_utils.go b/migrator/migrator_utils.go similarity index 81% rename from migrator/v1migrator_utils.go rename to migrator/migrator_utils.go index 1ca1ed321..50892c3e5 100644 --- a/migrator/v1migrator_utils.go +++ b/migrator/migrator_utils.go @@ -64,31 +64,12 @@ func NewMigratorStorDB(db_type, host, port, name, user, pass string, case utils.MYSQL: d = newMigratorSQL(storDb) db = d.(MigratorStorDB) + case utils.POSTGRES: + d = newMigratorSQL(storDb) + db = d.(MigratorStorDB) default: err = errors.New(fmt.Sprintf("Unknown db '%s' valid options are '%s' or '%s'", db_type, utils.MONGO, utils.MYSQL)) } return d, nil } - -/* - -func ConfigureV1StorDB(db_type, host, port, name, user, pass string) (db MigratorStorDB, err error) { - var d MigratorStorDB - switch db_type { - case utils.MONGO: - d, err = newv1MongoStorage(host, port, name, user, pass, utils.StorDB, nil) - db = d.(MigratorStorDB) - case utils.MYSQL: - d, err = newSqlStorage(host, port, name, user, pass) - db = d.(MigratorStorDB) - default: - err = errors.New(fmt.Sprintf("Unknown db '%s' valid options are '%s'", - db_type, utils.MONGO)) - } - if err != nil { - return nil, err - } - return d, nil -} -*/ diff --git a/migrator/sessions_costs.go b/migrator/sessions_costs.go index cebfb2565..931f9d735 100644 --- a/migrator/sessions_costs.go +++ b/migrator/sessions_costs.go @@ -19,7 +19,6 @@ along with this program. If not, see package migrator import ( - //"database/sql" "encoding/json" "fmt" "time" @@ -63,30 +62,10 @@ func (m *Migrator) migrateSessionSCosts() (err error) { "version number is not defined for SessionsCosts model") } switch vrs[utils.SessionSCosts] { - // case 0, 1: - // var isPostGres bool - // var storSQL *sql.DB - // switch m.storDBType { - // case utils.MYSQL: - // isPostGres = false - // storSQL = m.storDBOut.(*engine.SQLStorage).Db - // case utils.POSTGRES: - // isPostGres = true - // storSQL = m.storDBOut.(*engine.SQLStorage).Db - // default: - // return utils.NewCGRError(utils.Migrator, - // utils.MandatoryIEMissingCaps, - // utils.UnsupportedDB, - // fmt.Sprintf("unsupported database type: <%s>", m.storDBType)) - // } - // qry := "RENAME TABLE sm_costs TO sessions_costs;" - // if isPostGres { - // qry = "ALTER TABLE sm_costs RENAME TO sessions_costs" - // } - // if _, err := storSQL.Exec(qry); err != nil { - // return err - // } - // fallthrough // incremental updates + case 0, 1: + if err := m.migrateV1SessionSCosts(); err != nil { + return err + } case 2: if err := m.migrateV2SessionSCosts(); err != nil { return err @@ -99,6 +78,22 @@ func (m *Migrator) migrateSessionSCosts() (err error) { return nil } +func (m *Migrator) migrateV1SessionSCosts() (err error) { + if err = m.storDBIn.renameV1SMCosts(); err != nil { + return err + } + if m.dryRun != true { + vrs := engine.Versions{utils.SessionSCosts: 2} + if err = m.storDBOut.StorDB().SetVersions(vrs, false); err != nil { + return utils.NewCGRError(utils.Migrator, + utils.ServerErrorCaps, + err.Error(), + fmt.Sprintf("error: <%s> when updating SessionSCosts version into StorDB", err.Error())) + } + } + return +} + func (m *Migrator) migrateV2SessionSCosts() (err error) { var v2Cost *v2SessionsCost for { diff --git a/migrator/sessions_costs_it_test.go b/migrator/sessions_costs_it_test.go index 64302f645..9f93ebde8 100755 --- a/migrator/sessions_costs_it_test.go +++ b/migrator/sessions_costs_it_test.go @@ -20,9 +20,7 @@ along with this program. If not, see package migrator -/* import ( - "log" "path" "testing" "time" @@ -42,67 +40,46 @@ var ( ) var sTestssCostIT = []func(t *testing.T){ + testSessionCostITConnect, + testSessionCostITRename, testSessionCostITFlush, - testSessionCostITMigrateAndMove, + testSessionCostITMigrate, } -func TestSessionCostITMongoConnection(t *testing.T) { +func TestSessionCostITMongo(t *testing.T) { var err error sCostPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") sCostCfgIn, err = config.NewCGRConfigFromFolder(sCostPathIn) if err != nil { t.Error(err) } - storDBIn, err := engine.ConfigureStorDB(sCostCfgIn.StorDBType, sCostCfgIn.StorDBHost, - sCostCfgIn.StorDBPort, sCostCfgIn.StorDBName, - sCostCfgIn.StorDBUser, sCostCfgIn.StorDBPass, - config.CgrConfig().StorDBMaxOpenConns, - config.CgrConfig().StorDBMaxIdleConns, - config.CgrConfig().StorDBConnMaxLifetime, - config.CgrConfig().StorDBCDRSIndexes) + sCostCfgOut, err = config.NewCGRConfigFromFolder(sCostPathIn) if err != nil { t.Error(err) } - storDBOut, err := engine.ConfigureStorDB(sCostCfgIn.StorDBType, - sCostCfgIn.StorDBHost, sCostCfgIn.StorDBPort, sCostCfgIn.StorDBName, - sCostCfgIn.StorDBUser, sCostCfgIn.StorDBPass, - config.CgrConfig().StorDBMaxOpenConns, - config.CgrConfig().StorDBMaxIdleConns, - config.CgrConfig().StorDBConnMaxLifetime, - config.CgrConfig().StorDBCDRSIndexes) - if err != nil { - t.Error(err) - } - oldStorDB, err := ConfigureV1StorDB(sCostCfgIn.StorDBType, - sCostCfgIn.StorDBHost, sCostCfgIn.StorDBPort, sCostCfgIn.StorDBName, - sCostCfgIn.StorDBUser, sCostCfgIn.StorDBPass) - if err != nil { - log.Fatal(err) - } - - sCostMigrator, err = NewMigrator(nil, nil, sCostCfgIn.DataDbType, - sCostCfgIn.DBDataEncoding, storDBIn, storDBOut, sCostCfgIn.StorDBType, nil, - sCostCfgIn.DataDbType, sCostCfgIn.DBDataEncoding, oldStorDB, sCostCfgIn.StorDBType, - false, false, false, false, false) - if err != nil { - t.Error(err) - } -} - -func TestSessionCostITMongo(t *testing.T) { for _, stest := range sTestssCostIT { t.Run("TestSessionSCostITMigrateMongo", stest) } } -func TestSessionCostITMySqlConnection(t *testing.T) { +func TestSessionCostITMySql(t *testing.T) { var err error sCostPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") sCostCfgIn, err = config.NewCGRConfigFromFolder(sCostPathIn) if err != nil { t.Error(err) } - storDBIn, err := engine.ConfigureStorDB(sCostCfgIn.StorDBType, sCostCfgIn.StorDBHost, + sCostCfgOut, err = config.NewCGRConfigFromFolder(sCostPathIn) + if err != nil { + t.Error(err) + } + for _, stest := range sTestssCostIT { + t.Run("TestSessionSCostITMigrateMySql", stest) + } +} + +func testSessionCostITConnect(t *testing.T) { + storDBIn, err := NewMigratorStorDB(sCostCfgIn.StorDBType, sCostCfgIn.StorDBHost, sCostCfgIn.StorDBPort, sCostCfgIn.StorDBName, sCostCfgIn.StorDBUser, sCostCfgIn.StorDBPass, config.CgrConfig().StorDBMaxOpenConns, @@ -112,9 +89,9 @@ func TestSessionCostITMySqlConnection(t *testing.T) { if err != nil { t.Error(err) } - storDBOut, err := engine.ConfigureStorDB(sCostCfgIn.StorDBType, - sCostCfgIn.StorDBHost, sCostCfgIn.StorDBPort, sCostCfgIn.StorDBName, - sCostCfgIn.StorDBUser, sCostCfgIn.StorDBPass, + storDBOut, err := NewMigratorStorDB(sCostCfgOut.StorDBType, + sCostCfgOut.StorDBHost, sCostCfgOut.StorDBPort, sCostCfgOut.StorDBName, + sCostCfgOut.StorDBUser, sCostCfgOut.StorDBPass, config.CgrConfig().StorDBMaxOpenConns, config.CgrConfig().StorDBMaxIdleConns, config.CgrConfig().StorDBConnMaxLifetime, @@ -122,36 +99,51 @@ func TestSessionCostITMySqlConnection(t *testing.T) { if err != nil { t.Error(err) } - oldStorDB, err := ConfigureV1StorDB(sCostCfgIn.StorDBType, - sCostCfgIn.StorDBHost, sCostCfgIn.StorDBPort, sCostCfgIn.StorDBName, - sCostCfgIn.StorDBUser, sCostCfgIn.StorDBPass) - if err != nil { - log.Fatal(err) - } - - sCostMigrator, err = NewMigrator(nil, nil, sCostCfgIn.DataDbType, - sCostCfgIn.DBDataEncoding, storDBIn, storDBOut, sCostCfgIn.StorDBType, nil, - sCostCfgIn.DataDbType, sCostCfgIn.DBDataEncoding, oldStorDB, sCostCfgIn.StorDBType, - false, false, false, false, false) + sCostMigrator, err = NewMigrator(nil, nil, + storDBIn, storDBOut, + false, false, false) if err != nil { t.Error(err) } } -func TestSessionCostITMySql(t *testing.T) { - for _, stest := range sTestssCostIT { - t.Run("TestSessionSCostITMigrateMySql", stest) +func testSessionCostITRename(t *testing.T) { + var err error + if err = sCostMigrator.storDBIn.createV1SMCosts(); err != nil { + t.Error(err) } + currentVersion := engine.Versions{ + utils.SessionSCosts: 1, + } + err = sCostMigrator.storDBOut.StorDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for SessionsCosts ", err.Error()) + } + if vrs, err := sCostMigrator.storDBOut.StorDB().GetVersions(""); err != nil { + t.Error(err) + } else if vrs[utils.SessionSCosts] != 1 { + t.Errorf("Unexpected version returned: %d", vrs[utils.SessionSCosts]) + } + err, _ = sCostMigrator.Migrate([]string{utils.MetaSessionsCosts}) + if err != nil { + t.Error("Error when migrating SessionsCosts ", err.Error()) + } + if vrs, err := sCostMigrator.storDBOut.StorDB().GetVersions(""); err != nil { + t.Error(err) + } else if vrs[utils.SessionSCosts] != 2 { + t.Errorf("Unexpected version returned: %d", vrs[utils.SessionSCosts]) + } + } func testSessionCostITFlush(t *testing.T) { - if err := sCostMigrator.storDBOut.Flush( + if err := sCostMigrator.storDBOut.StorDB().Flush( path.Join(sCostCfgIn.DataFolderPath, "storage", sCostCfgIn.StorDBType)); err != nil { t.Error(err) } } -func testSessionCostITMigrateAndMove(t *testing.T) { +func testSessionCostITMigrate(t *testing.T) { cc := &engine.CallCost{ Direction: utils.OUT, Cost: 1.23, @@ -187,17 +179,17 @@ func testSessionCostITMigrateAndMove(t *testing.T) { CostDetails: cc, } var err error - if err = sCostMigrator.oldStorDB.setSMCost(v2Cost); err != nil { + if err = sCostMigrator.storDBIn.setV2SMCost(v2Cost); err != nil { t.Error(err) } currentVersion := engine.Versions{ utils.SessionSCosts: 2, } - err = sCostMigrator.storDBOut.SetVersions(currentVersion, false) + err = sCostMigrator.storDBOut.StorDB().SetVersions(currentVersion, false) if err != nil { t.Error("Error when setting version for SessionsCosts ", err.Error()) } - if vrs, err := sCostMigrator.storDBOut.GetVersions(""); err != nil { + if vrs, err := sCostMigrator.storDBOut.StorDB().GetVersions(""); err != nil { t.Error(err) } else if vrs[utils.SessionSCosts] != 2 { t.Errorf("Unexpected version returned: %d", vrs[utils.SessionSCosts]) @@ -206,15 +198,14 @@ func testSessionCostITMigrateAndMove(t *testing.T) { if err != nil { t.Error("Error when migrating SessionsCosts ", err.Error()) } - if rcvCosts, err := sCostMigrator.storDBOut.GetSMCosts("", utils.DEFAULT_RUNID, "", ""); err != nil { + if rcvCosts, err := sCostMigrator.storDBOut.StorDB().GetSMCosts("", utils.DEFAULT_RUNID, "", ""); err != nil { t.Error(err) } else if len(rcvCosts) != 1 { t.Errorf("Unexpected number of SessionsCosts returned: %d", len(rcvCosts)) } - if vrs, err := sCostMigrator.storDBOut.GetVersions(""); err != nil { + if vrs, err := sCostMigrator.storDBOut.StorDB().GetVersions(""); err != nil { t.Error(err) } else if vrs[utils.SessionSCosts] != 3 { t.Errorf("Unexpected version returned: %d", vrs[utils.SessionSCosts]) } } -*/ diff --git a/migrator/sharedgroup_it_test.go b/migrator/sharedgroup_it_test.go new file mode 100644 index 000000000..66c344ff4 --- /dev/null +++ b/migrator/sharedgroup_it_test.go @@ -0,0 +1,226 @@ +// +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 migrator + +import ( + "log" + "path" + "reflect" + "testing" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + shrGrpPathIn string + shrGrpPathOut string + shrGrpCfgIn *config.CGRConfig + shrGrpCfgOut *config.CGRConfig + shrGrpMigrator *Migrator + shrSharedGroup string +) + +var sTestsShrGrpIT = []func(t *testing.T){ + testShrGrpITConnect, + testShrGrpITFlush, + testShrGrpITMigrateAndMove, +} + +func TestSharedGroupITRedis(t *testing.T) { + var err error + shrGrpPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + shrGrpCfgIn, err = config.NewCGRConfigFromFolder(shrGrpPathIn) + if err != nil { + t.Fatal(err) + } + shrGrpCfgOut, err = config.NewCGRConfigFromFolder(shrGrpPathIn) + if err != nil { + t.Fatal(err) + } + shrSharedGroup = utils.Migrate + for _, stest := range sTestsShrGrpIT { + t.Run("TestSharedGroupITMigrateRedis", stest) + } +} + +func TestSharedGroupITMongo(t *testing.T) { + var err error + shrGrpPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + shrGrpCfgIn, err = config.NewCGRConfigFromFolder(shrGrpPathIn) + if err != nil { + t.Fatal(err) + } + shrGrpCfgOut, err = config.NewCGRConfigFromFolder(shrGrpPathIn) + if err != nil { + t.Fatal(err) + } + shrSharedGroup = utils.Migrate + for _, stest := range sTestsShrGrpIT { + t.Run("TestSharedGroupITMigrateMongo", stest) + } +} + +func TestSharedGroupITMove(t *testing.T) { + var err error + shrGrpPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + shrGrpCfgIn, err = config.NewCGRConfigFromFolder(shrGrpPathIn) + if err != nil { + t.Fatal(err) + } + shrGrpPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + shrGrpCfgOut, err = config.NewCGRConfigFromFolder(shrGrpPathOut) + if err != nil { + t.Fatal(err) + } + shrSharedGroup = utils.Move + for _, stest := range sTestsShrGrpIT { + t.Run("TestSharedGroupITMove", stest) + } +} + +func TestSharedGroupITMoveEncoding(t *testing.T) { + var err error + shrGrpPathIn = path.Join(*dataDir, "conf", "samples", "tutmongojson") + shrGrpCfgIn, err = config.NewCGRConfigFromFolder(shrGrpPathIn) + if err != nil { + t.Fatal(err) + } + shrGrpPathOut = path.Join(*dataDir, "conf", "samples", "tutmongomsgpack") + shrGrpCfgOut, err = config.NewCGRConfigFromFolder(shrGrpPathOut) + if err != nil { + t.Fatal(err) + } + shrSharedGroup = utils.Move + for _, stest := range sTestsShrGrpIT { + t.Run("TestSharedGroupITMoveEncoding", stest) + } +} + +func TestSharedGroupITMoveEncoding2(t *testing.T) { + var err error + shrGrpPathIn = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + shrGrpCfgIn, err = config.NewCGRConfigFromFolder(shrGrpPathIn) + if err != nil { + t.Fatal(err) + } + shrGrpPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqlmsgpack") + shrGrpCfgOut, err = config.NewCGRConfigFromFolder(shrGrpPathOut) + if err != nil { + t.Fatal(err) + } + shrSharedGroup = utils.Move + for _, stest := range sTestsShrGrpIT { + t.Run("TestSharedGroupITMoveEncoding2", stest) + } +} + +func testShrGrpITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(shrGrpCfgIn.DataDbType, + shrGrpCfgIn.DataDbHost, shrGrpCfgIn.DataDbPort, shrGrpCfgIn.DataDbName, + shrGrpCfgIn.DataDbUser, shrGrpCfgIn.DataDbPass, shrGrpCfgIn.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(shrGrpCfgOut.DataDbType, + shrGrpCfgOut.DataDbHost, shrGrpCfgOut.DataDbPort, shrGrpCfgOut.DataDbName, + shrGrpCfgOut.DataDbUser, shrGrpCfgOut.DataDbPass, shrGrpCfgOut.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + shrGrpMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testShrGrpITFlush(t *testing.T) { + shrGrpMigrator.dmOut.DataManager().DataDB().Flush("") + if err := engine.SetDBVersions(shrGrpMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testShrGrpITMigrateAndMove(t *testing.T) { + v1shrGrp := &v1SharedGroup{ + Id: "Test", + AccountParameters: map[string]*engine.SharingParameters{ + "test": &engine.SharingParameters{Strategy: "*highest"}, + }, + MemberIds: []string{"1", "2", "3"}, + } + shrGrp := &engine.SharedGroup{ + Id: "Test", + AccountParameters: map[string]*engine.SharingParameters{ + "test": &engine.SharingParameters{Strategy: "*highest"}, + }, + MemberIds: utils.NewStringMap("1", "2", "3"), + } + + switch shrSharedGroup { + case utils.Migrate: + err := shrGrpMigrator.dmIN.setV1SharedGroup(v1shrGrp) + if err != nil { + t.Error("Error when setting v1 SharedGroup ", err.Error()) + } + currentVersion := engine.Versions{utils.StatS: 2, utils.Thresholds: 2, utils.Accounts: 2, utils.Actions: 2, utils.ActionTriggers: 2, utils.ActionPlans: 2, utils.SharedGroups: 1} + err = shrGrpMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for SharedGroup ", err.Error()) + } + err, _ = shrGrpMigrator.Migrate([]string{utils.MetaSharedGroups}) + if err != nil { + t.Error("Error when migrating SharedGroup ", err.Error()) + } + result, err := shrGrpMigrator.dmOut.DataManager().GetSharedGroup(v1shrGrp.Id, true, utils.NonTransactional) + if err != nil { + t.Error("Error when getting SharedGroup ", err.Error()) + } + if !reflect.DeepEqual(shrGrp, result) { + t.Errorf("Expecting: %+v, received: %+v", shrGrp, result) + } + case utils.Move: + if err := shrGrpMigrator.dmIN.DataManager().SetSharedGroup(shrGrp, utils.NonTransactional); err != nil { + t.Error("Error when setting SharedGroup ", err.Error()) + } + currentVersion := engine.CurrentDataDBVersions() + err := shrGrpMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for SharedGroup ", err.Error()) + } + err, _ = shrGrpMigrator.Migrate([]string{utils.MetaSharedGroups}) + if err != nil { + t.Error("Error when migrating SharedGroup ", err.Error()) + } + result, err := shrGrpMigrator.dmOut.DataManager().GetSharedGroup(v1shrGrp.Id, true, utils.NonTransactional) + if err != nil { + t.Error("Error when getting SharedGroup ", err.Error()) + } + if !reflect.DeepEqual(shrGrp, result) { + t.Errorf("Expecting: %+v, received: %+v", shrGrp, result) + } + } +} diff --git a/migrator/stats_it_test.go b/migrator/stats_it_test.go index d35d99f10..34b39a962 100755 --- a/migrator/stats_it_test.go +++ b/migrator/stats_it_test.go @@ -20,7 +20,6 @@ along with this program. If not, see package migrator -/* import ( "log" "path" @@ -102,38 +101,31 @@ func TestStatsQueueITMove(t *testing.T) { } func testStsITConnect(t *testing.T) { - dataDBIn, err := engine.ConfigureDataStorage(stsCfgIn.DataDbType, + dataDBIn, err := NewMigratorDataDB(stsCfgIn.DataDbType, stsCfgIn.DataDbHost, stsCfgIn.DataDbPort, stsCfgIn.DataDbName, stsCfgIn.DataDbUser, stsCfgIn.DataDbPass, stsCfgIn.DBDataEncoding, config.CgrConfig().CacheCfg(), *loadHistorySize) if err != nil { log.Fatal(err) } - dataDBOut, err := engine.ConfigureDataStorage(stsCfgOut.DataDbType, + dataDBOut, err := NewMigratorDataDB(stsCfgOut.DataDbType, stsCfgOut.DataDbHost, stsCfgOut.DataDbPort, stsCfgOut.DataDbName, stsCfgOut.DataDbUser, stsCfgOut.DataDbPass, stsCfgOut.DBDataEncoding, config.CgrConfig().CacheCfg(), *loadHistorySize) if err != nil { log.Fatal(err) } - oldDataDB, err := ConfigureV1DataStorage(stsCfgIn.DataDbType, - stsCfgIn.DataDbHost, stsCfgIn.DataDbPort, stsCfgIn.DataDbName, - stsCfgIn.DataDbUser, stsCfgIn.DataDbPass, stsCfgIn.DBDataEncoding) - if err != nil { - log.Fatal(err) - } - stsMigrator, err = NewMigrator(dataDBIn, dataDBOut, stsCfgIn.DataDbType, - stsCfgIn.DBDataEncoding, nil, nil, stsCfgIn.StorDBType, oldDataDB, - stsCfgIn.DataDbType, stsCfgIn.DBDataEncoding, nil, stsCfgIn.StorDBType, - false, false, false, false, false) + stsMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false) if err != nil { log.Fatal(err) } } func testStsITFlush(t *testing.T) { - stsMigrator.dmOut.DataDB().Flush("") - if err := engine.SetDBVersions(stsMigrator.dmOut.DataDB()); err != nil { + stsMigrator.dmOut.DataManager().DataDB().Flush("") + if err := engine.SetDBVersions(stsMigrator.dmOut.DataManager().DataDB()); err != nil { t.Error("Error ", err.Error()) } } @@ -237,7 +229,7 @@ func testStsITMigrateAndMove(t *testing.T) { } switch stsAction { case utils.Migrate: - err := stsMigrator.oldDataDB.setV1Stats(v1Sts) + err := stsMigrator.dmIN.setV1Stats(v1Sts) if err != nil { t.Error("Error when setting v1Stat ", err.Error()) } @@ -249,7 +241,7 @@ func testStsITMigrateAndMove(t *testing.T) { utils.ActionTriggers: 2, utils.ActionPlans: 2, utils.SharedGroups: 2} - err = stsMigrator.dmOut.DataDB().SetVersions(currentVersion, false) + err = stsMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) if err != nil { t.Error("Error when setting version for stats ", err.Error()) } @@ -258,8 +250,7 @@ func testStsITMigrateAndMove(t *testing.T) { t.Error("Error when migrating Stats ", err.Error()) } - result, err := stsMigrator.dmOut.GetStatQueueProfile("cgrates.org", - v1Sts.Id, true, utils.NonTransactional) + result, err := stsMigrator.dmOut.DataManager().DataDB().GetStatQueueProfileDrv("cgrates.org", v1Sts.Id) if err != nil { t.Error("Error when getting Stats ", err.Error()) } @@ -267,8 +258,7 @@ func testStsITMigrateAndMove(t *testing.T) { t.Errorf("Expecting: %+v, received: %+v", sqp, result) } - result1, err := stsMigrator.dmOut.GetFilter("cgrates.org", - v1Sts.Id, true, utils.NonTransactional) + result1, err := stsMigrator.dmOut.DataManager().DataDB().GetFilterDrv("cgrates.org", v1Sts.Id) if err != nil { t.Error("Error when getting Stats ", err.Error()) } @@ -278,7 +268,7 @@ func testStsITMigrateAndMove(t *testing.T) { t.Errorf("Expecting: %+v, received: %+v", len(filter.Rules), len(result1.Rules)) } - result2, err := stsMigrator.dmOut.GetStatQueue("cgrates.org", sq.ID, true, utils.NonTransactional) + result2, err := stsMigrator.dmOut.DataManager().GetStatQueue("cgrates.org", sq.ID, true, utils.NonTransactional) if err != nil { t.Error("Error when getting Stats ", err.Error()) } @@ -287,14 +277,14 @@ func testStsITMigrateAndMove(t *testing.T) { } case utils.Move: - if err := stsMigrator.dmIN.SetStatQueueProfile(sqp, true); err != nil { + if err := stsMigrator.dmIN.DataManager().DataDB().SetStatQueueProfileDrv(sqp); err != nil { t.Error("Error when setting Stats ", err.Error()) } - if err := stsMigrator.dmIN.SetStatQueue(sq); err != nil { + if err := stsMigrator.dmIN.DataManager().SetStatQueue(sq); err != nil { t.Error("Error when setting Stats ", err.Error()) } currentVersion := engine.CurrentDataDBVersions() - err := stsMigrator.dmOut.DataDB().SetVersions(currentVersion, false) + err := stsMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) if err != nil { t.Error("Error when setting version for stats ", err.Error()) } @@ -302,11 +292,11 @@ func testStsITMigrateAndMove(t *testing.T) { if err != nil { t.Error("Error when migrating Stats ", err.Error()) } - result, err := stsMigrator.dmOut.GetStatQueueProfile(sqp.Tenant, sqp.ID, true, utils.NonTransactional) + result, err := stsMigrator.dmOut.DataManager().DataDB().GetStatQueueProfileDrv(sqp.Tenant, sqp.ID) if err != nil { t.Error("Error when getting Stats ", err.Error()) } - result1, err := stsMigrator.dmOut.GetStatQueue(sq.Tenant, sq.ID, true, utils.NonTransactional) + result1, err := stsMigrator.dmOut.DataManager().GetStatQueue(sq.Tenant, sq.ID, true, utils.NonTransactional) if err != nil { t.Error("Error when getting Stats ", err.Error()) } @@ -319,4 +309,3 @@ func testStsITMigrateAndMove(t *testing.T) { } } -*/ diff --git a/migrator/v1mongo_data.go b/migrator/storage_mongo_datadb.go similarity index 100% rename from migrator/v1mongo_data.go rename to migrator/storage_mongo_datadb.go diff --git a/migrator/v1mongo_stor.go b/migrator/storage_mongo_stordb.go similarity index 76% rename from migrator/v1mongo_stor.go rename to migrator/storage_mongo_stordb.go index 34f383310..d13c96412 100755 --- a/migrator/v1mongo_stor.go +++ b/migrator/storage_mongo_stordb.go @@ -22,6 +22,7 @@ import ( "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" "github.com/cgrates/mgo" + "github.com/cgrates/mgo/bson" ) func newMongoStorDBMigrator(stor engine.StorDB) (mgoMig *mongoStorDBMigrator) { @@ -67,6 +68,23 @@ func (v1ms *mongoStorDBMigrator) setV1CDR(v1Cdr *v1Cdrs) (err error) { } //SMCost methods +//rename +func (v1ms *mongoStorDBMigrator) renameV1SMCosts() (err error) { + if err = v1ms.mgoDB.DB().C(utils.OldSMCosts).DropCollection(); err != nil { + return err + } + result := make(map[string]string) + return v1ms.mgoDB.DB().Run(bson.D{{"create", utils.SessionsCostsTBL}}, result) +} + +func (v1ms *mongoStorDBMigrator) createV1SMCosts() (err error) { + err = v1ms.mgoDB.DB().C(utils.OldSMCosts).DropCollection() + err = v1ms.mgoDB.DB().C(utils.SessionsCostsTBL).DropCollection() + result := make(map[string]string) + return v1ms.mgoDB.DB().Run(bson.D{{"create", utils.OldSMCosts}, + {"size", 1024}}, result) +} + //get func (v1ms *mongoStorDBMigrator) getV2SMCost() (v2Cost *v2SessionsCost, err error) { if v1ms.qryIter == nil { diff --git a/migrator/v1redis.go b/migrator/storage_redis.go similarity index 100% rename from migrator/v1redis.go rename to migrator/storage_redis.go diff --git a/migrator/v1sql.go b/migrator/storage_sql.go similarity index 63% rename from migrator/v1sql.go rename to migrator/storage_sql.go index 48fa08dbe..b4d42039c 100755 --- a/migrator/v1sql.go +++ b/migrator/storage_sql.go @@ -20,6 +20,7 @@ package migrator import ( "database/sql" + "fmt" "time" "github.com/cgrates/cgrates/engine" @@ -75,6 +76,48 @@ func (mgSQL *migratorSQL) setV1CDR(v1Cdr *v1Cdrs) (err error) { return nil } +func (mgSQL *migratorSQL) renameV1SMCosts() (err error) { + qry := "RENAME TABLE sm_costs TO sessions_costs;" + if mgSQL.StorDB().GetStorageType() == utils.POSTGRES { + qry = "ALTER TABLE sm_costs RENAME TO sessions_costs" + } + if _, err := mgSQL.sqlStorage.Db.Exec(qry); err != nil { + return err + } + return +} + +func (mgSQL *migratorSQL) createV1SMCosts() (err error) { + qry := fmt.Sprint("CREATE TABLE sm_costs ( id int(11) NOT NULL AUTO_INCREMENT, cgrid varchar(40) NOT NULL, run_id varchar(64) NOT NULL, origin_host varchar(64) NOT NULL, origin_id varchar(128) NOT NULL, cost_source varchar(64) NOT NULL, `usage` BIGINT NOT NULL, cost_details MEDIUMTEXT, created_at TIMESTAMP NULL,deleted_at TIMESTAMP NULL, PRIMARY KEY (`id`),UNIQUE KEY costid (cgrid, run_id),KEY origin_idx (origin_host, origin_id),KEY run_origin_idx (run_id, origin_id),KEY deleted_at_idx (deleted_at));") + if mgSQL.StorDB().GetStorageType() == utils.POSTGRES { + qry = ` + CREATE TABLE sm_costs ( + id SERIAL PRIMARY KEY, + cgrid VARCHAR(40) NOT NULL, + run_id VARCHAR(64) NOT NULL, + origin_host VARCHAR(64) NOT NULL, + origin_id VARCHAR(128) NOT NULL, + cost_source VARCHAR(64) NOT NULL, + usage BIGINT NOT NULL, + cost_details jsonb, + created_at TIMESTAMP WITH TIME ZONE, + deleted_at TIMESTAMP WITH TIME ZONE NULL, + UNIQUE (cgrid, run_id) + ); + ` + } + if _, err := mgSQL.sqlStorage.Db.Exec("DROP TABLE IF EXISTS sessions_costs;"); err != nil { + return err + } + if _, err := mgSQL.sqlStorage.Db.Exec("DROP TABLE IF EXISTS sm_costs;"); err != nil { + return err + } + if _, err := mgSQL.sqlStorage.Db.Exec(qry); err != nil { + return err + } + return +} + func (mgSQL *migratorSQL) getV2SMCost() (v2Cost *v2SessionsCost, err error) { if mgSQL.rowIter == nil { mgSQL.rowIter, err = mgSQL.sqlStorage.Db.Query("SELECT * FROM sessions_costs") diff --git a/migrator/thresholds_it_test.go b/migrator/thresholds_it_test.go new file mode 100644 index 000000000..67144fd50 --- /dev/null +++ b/migrator/thresholds_it_test.go @@ -0,0 +1,265 @@ +// +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 migrator + +import ( + "log" + "path" + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + trsPathIn string + trsPathOut string + trsCfgIn *config.CGRConfig + trsCfgOut *config.CGRConfig + trsMigrator *Migrator + trsThresholds string +) + +var sTestsTrsIT = []func(t *testing.T){ + testTrsITConnect, + testTrsITFlush, + testTrsITMigrateAndMove, +} + +func TestThresholdsITRedis(t *testing.T) { + var err error + trsPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + trsCfgIn, err = config.NewCGRConfigFromFolder(trsPathIn) + if err != nil { + t.Fatal(err) + } + trsCfgOut, err = config.NewCGRConfigFromFolder(trsPathIn) + if err != nil { + t.Fatal(err) + } + trsThresholds = utils.Migrate + for _, stest := range sTestsTrsIT { + t.Run("TestThresholdsITMigrateRedis", stest) + } +} + +func TestThresholdsITMongo(t *testing.T) { + var err error + trsPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + trsCfgIn, err = config.NewCGRConfigFromFolder(trsPathIn) + if err != nil { + t.Fatal(err) + } + trsCfgOut, err = config.NewCGRConfigFromFolder(trsPathIn) + if err != nil { + t.Fatal(err) + } + trsThresholds = utils.Migrate + for _, stest := range sTestsTrsIT { + t.Run("TestThresholdsITMigrateMongo", stest) + } +} + +func TestThresholdsITMove(t *testing.T) { + var err error + trsPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + trsCfgIn, err = config.NewCGRConfigFromFolder(trsPathIn) + if err != nil { + t.Fatal(err) + } + trsPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + trsCfgOut, err = config.NewCGRConfigFromFolder(trsPathOut) + if err != nil { + t.Fatal(err) + } + trsThresholds = utils.Move + for _, stest := range sTestsTrsIT { + t.Run("TestThresholdsITMove", stest) + } +} + +func TestThresholdsITMoveEncoding(t *testing.T) { + var err error + trsPathIn = path.Join(*dataDir, "conf", "samples", "tutmongojson") + trsCfgIn, err = config.NewCGRConfigFromFolder(trsPathIn) + if err != nil { + t.Fatal(err) + } + trsPathOut = path.Join(*dataDir, "conf", "samples", "tutmongomsgpack") + trsCfgOut, err = config.NewCGRConfigFromFolder(trsPathOut) + if err != nil { + t.Fatal(err) + } + trsThresholds = utils.Move + for _, stest := range sTestsTrsIT { + t.Run("TestThresholdsITMoveEncoding", stest) + } +} + +func TestThresholdsITMoveEncoding2(t *testing.T) { + var err error + trsPathIn = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + trsCfgIn, err = config.NewCGRConfigFromFolder(trsPathIn) + if err != nil { + t.Fatal(err) + } + trsPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqlmsgpack") + trsCfgOut, err = config.NewCGRConfigFromFolder(trsPathOut) + if err != nil { + t.Fatal(err) + } + trsThresholds = utils.Move + for _, stest := range sTestsTrsIT { + t.Run("TestThresholdsITMoveEncoding2", stest) + } +} + +func testTrsITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(trsCfgIn.DataDbType, + trsCfgIn.DataDbHost, trsCfgIn.DataDbPort, trsCfgIn.DataDbName, + trsCfgIn.DataDbUser, trsCfgIn.DataDbPass, trsCfgIn.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(trsCfgOut.DataDbType, + trsCfgOut.DataDbHost, trsCfgOut.DataDbPort, trsCfgOut.DataDbName, + trsCfgOut.DataDbUser, trsCfgOut.DataDbPass, trsCfgOut.DBDataEncoding, + config.CgrConfig().CacheCfg(), *loadHistorySize) + if err != nil { + log.Fatal(err) + } + trsMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testTrsITFlush(t *testing.T) { + trsMigrator.dmOut.DataManager().DataDB().Flush("") + if err := engine.SetDBVersions(trsMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testTrsITMigrateAndMove(t *testing.T) { + tim := time.Date(2012, time.February, 27, 23, 59, 59, 0, time.UTC) + var filters []*engine.FilterRule + v1trs := &v2ActionTrigger{ + ID: "test2", // original csv tag + UniqueID: "testUUID", // individual id + ThresholdType: "*min_event_counter", //*min_event_counter, *max_event_counter, *min_balance_counter, *max_balance_counter, *min_balance, *max_balance, *balance_expired + ThresholdValue: 5.32, + Recurrent: false, // reset excuted flag each run + MinSleep: time.Duration(5) * time.Second, // Minimum duration between two executions in case of recurrent triggers + ExpirationDate: tim, + ActivationDate: tim, + Balance: &engine.BalanceFilter{ + ID: utils.StringPointer("TESTZ"), + Timings: []*engine.RITiming{}, + ExpirationDate: utils.TimePointer(tim), + Type: utils.StringPointer(utils.MONETARY), + Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), + }, + Weight: 0, + ActionsID: "Action1", + MinQueuedItems: 10, // Trigger actions only if this number is hit (stats only) + Executed: false, + LastExecutionTime: time.Now(), + } + x, err := engine.NewFilterRule(engine.MetaRSR, "Directions", v1trs.Balance.Directions.Slice()) + if err != nil { + t.Error("Error when creating new NewFilterRule", err.Error()) + } + filters = append(filters, x) + + tresProf := &engine.ThresholdProfile{ + ID: v1trs.ID, + Tenant: config.CgrConfig().DefaultTenant, + Weight: v1trs.Weight, + ActivationInterval: &utils.ActivationInterval{v1trs.ExpirationDate, v1trs.ActivationDate}, + MinSleep: v1trs.MinSleep, + } + switch trsThresholds { + case utils.Migrate: + err := trsMigrator.dmIN.setV2ActionTrigger(v1trs) + if err != nil { + t.Error("Error when setting v1 Thresholds ", err.Error()) + } + currentVersion := engine.Versions{utils.StatS: 2, utils.Thresholds: 1, utils.Accounts: 2, utils.Actions: 2, utils.ActionTriggers: 2, utils.ActionPlans: 2, utils.SharedGroups: 2} + err = trsMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for Thresholds ", err.Error()) + } + err, _ = trsMigrator.Migrate([]string{utils.MetaThresholds}) + if err != nil { + t.Error("Error when migrating Thresholds ", err.Error()) + } + result, err := trsMigrator.dmOut.DataManager().GetThresholdProfile(tresProf.Tenant, tresProf.ID, false, utils.NonTransactional) + if err != nil { + t.Error("Error when getting Thresholds ", err.Error()) + } + if !reflect.DeepEqual(tresProf.ID, result.ID) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.ID, result.ID) + } else if !reflect.DeepEqual(tresProf.Tenant, result.Tenant) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.Tenant, result.Tenant) + } else if !reflect.DeepEqual(tresProf.Weight, result.Weight) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.Weight, result.Weight) + } else if !reflect.DeepEqual(tresProf.ActivationInterval, result.ActivationInterval) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.ActivationInterval, result.ActivationInterval) + } else if !reflect.DeepEqual(tresProf.MinSleep, result.MinSleep) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.MinSleep, result.MinSleep) + } + case utils.Move: + if err := trsMigrator.dmIN.DataManager().SetThresholdProfile(tresProf, false); err != nil { + t.Error("Error when setting Thresholds ", err.Error()) + } + currentVersion := engine.CurrentDataDBVersions() + err := trsMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for Thresholds ", err.Error()) + } + err, _ = trsMigrator.Migrate([]string{utils.MetaSharedGroups}) + if err != nil { + t.Error("Error when migrating Thresholds ", err.Error()) + } + result, err := trsMigrator.dmOut.DataManager().GetThresholdProfile(tresProf.Tenant, tresProf.ID, false, utils.NonTransactional) + if err != nil { + t.Error("Error when getting Thresholds ", err.Error()) + } + if !reflect.DeepEqual(tresProf.ID, result.ID) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.ID, result.ID) + } else if !reflect.DeepEqual(tresProf.Tenant, result.Tenant) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.Tenant, result.Tenant) + } else if !reflect.DeepEqual(tresProf.Weight, result.Weight) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.Weight, result.Weight) + } else if !reflect.DeepEqual(tresProf.ActivationInterval, result.ActivationInterval) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.ActivationInterval, result.ActivationInterval) + } else if !reflect.DeepEqual(tresProf.MinSleep, result.MinSleep) { + t.Errorf("Expecting: %+v, received: %+v", tresProf.MinSleep, result.MinSleep) + } + } +} diff --git a/utils/consts.go b/utils/consts.go index b49fb551c..d57bf32eb 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -535,6 +535,7 @@ const ( Freeswitch = "freeswitch" Kamailio = "kamailio" Opensips = "opensips" + Asterisk = "asterisk" ) // Migrator Action @@ -778,6 +779,7 @@ const ( TBLTPSuppliers = "tp_suppliers" TBLTPAttributes = "tp_attributes" TBLVersions = "versions" + OldSMCosts = "sm_costs" ) // Cache Name @@ -841,6 +843,7 @@ const ( RadiusAgent = "RadiusAgent" DiameterAgent = "DiameterAgent" FreeSWITCHAgent = "FreeSWITCHAgent" + AsteriskAgent = "AsteriskAgent" ) func buildCacheInstRevPrefixes() {