/* 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 engine import ( "encoding/json" "reflect" "testing" "time" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) func TestNewCDRFromExternalCDR(t *testing.T) { extCdr := &ExternalCDR{ // CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.MetaDefault, Usage: "10", Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } eStorCdr := &CDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, RunID: utils.MetaDefault, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: 10, Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } if CDR, err := NewCDRFromExternalCDR(extCdr, ""); err != nil { t.Error(err) } else if !reflect.DeepEqual(eStorCdr, CDR) { t.Errorf("Expected: %+v, received: %+v", eStorCdr, CDR) } } func TestCDRClone(t *testing.T) { storCdr := &CDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.MetaDefault, Usage: 10, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, PreRated: true, } if clnStorCdr := storCdr.Clone(); !reflect.DeepEqual(storCdr, clnStorCdr) { t.Errorf("Expecting: %+v, received: %+v", storCdr, clnStorCdr) } } func TestFieldsAsString(t *testing.T) { cdr := CDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: "test", RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.MetaDefault, Usage: 10 * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, } eVal := "call_from_1001" if val := cdr.FieldsAsString( config.NewRSRParsersMustCompile("~*req.Category;_from_;~*req.Account", utils.InfieldSep)); val != eVal { t.Errorf("Expecting : %s, received: %q", eVal, val) } } func TestFormatCost(t *testing.T) { cdr := CDR{Cost: 1.01} if cdr.FormatCost(0, 4) != "1.0100" { t.Error("Unexpected format of the cost: ", cdr.FormatCost(0, 4)) } cdr = CDR{Cost: 1.01001} if cdr.FormatCost(0, 4) != "1.0100" { t.Error("Unexpected format of the cost: ", cdr.FormatCost(0, 4)) } if cdr.FormatCost(2, 0) != "101" { t.Error("Unexpected format of the cost: ", cdr.FormatCost(2, 0)) } if cdr.FormatCost(1, 0) != "10" { t.Error("Unexpected format of the cost: ", cdr.FormatCost(1, 0)) } if cdr.FormatCost(2, 3) != "101.001" { t.Error("Unexpected format of the cost: ", cdr.FormatCost(2, 3)) } } func TestCDRAsMapStringIface(t *testing.T) { cdr := &CDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1002", Subject: "1001", Destination: "+4986517174963", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.MetaDefault, Usage: 10 * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, } mp := map[string]interface{}{ "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.RunID: utils.MetaDefault, utils.OrderID: cdr.OrderID, utils.OriginHost: "192.168.1.1", utils.Source: utils.UnitTest, utils.OriginID: "dsafdsaf", utils.ToR: utils.MetaVoice, utils.RequestType: utils.MetaRated, utils.Tenant: "cgrates.org", utils.Category: "call", utils.AccountField: "1002", utils.Subject: "1001", utils.Destination: "+4986517174963", utils.SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), utils.AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), utils.Usage: 10 * time.Second, utils.CostSource: cdr.CostSource, utils.Cost: 1.01, utils.PreRated: false, utils.Partial: false, utils.ExtraInfo: cdr.ExtraInfo, } if cdrMp := cdr.AsMapStringIface(); !reflect.DeepEqual(mp, cdrMp) { t.Errorf("Expecting: %+v, received: %+v", mp, cdrMp) } } func TestCDRNewCDRFromSQL(t *testing.T) { extraFields := map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"} cdrSQL := &CDRsql{ ID: 123, // Cgrid: "abecd993d06672714c4218a6dcf8278e0589a171", RunID: utils.MetaDefault, OriginID: "dsafdsaf", TOR: utils.MetaVoice, Source: utils.UnitTest, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "+4986517174963", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: utils.TimePointer(time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC)), Usage: 10000000000, Cost: 1.01, RequestType: utils.MetaRated, OriginHost: "192.168.1.1", ExtraFields: utils.ToJSON(extraFields), } cdr := &CDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "+4986517174963", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.MetaDefault, Usage: 10 * time.Second, Cost: 1.01, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } if eCDR, err := NewCDRFromSQL(cdrSQL); err != nil { t.Error(err) } else if !reflect.DeepEqual(cdr, eCDR) { t.Errorf("Expecting: %+v, received: %+v", cdr, eCDR) } } func TestCDRAsCGREvent(t *testing.T) { cdr := &CDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "+4986517174963", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), RunID: utils.MetaDefault, Usage: 10 * time.Second, Cost: 1.01, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } eCGREvent := utils.CGREvent{ Tenant: "cgrates.org", ID: "GenePreRated", Event: map[string]interface{}{ "Account": "1001", "AnswerTime": time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), "Category": "call", "Cost": 1.01, "CostSource": "", "Destination": "+4986517174963", "ExtraInfo": "", "OrderID": int64(123), "OriginHost": "192.168.1.1", "OriginID": "dsafdsaf", "Partial": false, "RequestType": utils.MetaRated, "RunID": utils.MetaDefault, "SetupTime": time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), "Source": "UNIT_TEST", "Subject": "1001", "Tenant": "cgrates.org", "ToR": "*voice", "Usage": 10 * time.Second, "field_extr1": "val_extr1", "fieldextr2": "valextr2", "PreRated": false, }, } cgrEvent := cdr.AsCGREvent() if !reflect.DeepEqual(eCGREvent.Tenant, cgrEvent.Tenant) { t.Errorf("Expecting: %+v, received: %+v", eCGREvent.Tenant, cgrEvent.Tenant) } for fldName, fldVal := range eCGREvent.Event { if _, has := cgrEvent.Event[fldName]; !has { t.Errorf("Expecting: %+v, received: %+v", fldName, nil) } else if fldVal != cgrEvent.Event[fldName] { t.Errorf("Expecting: %s:%+v, received: %s:%+v", fldName, eCGREvent.Event[fldName], fldName, cgrEvent.Event[fldName]) } } } func TestCDRAddDefaults(t *testing.T) { cdr := &CDR{ OriginID: "dsafdsaf", OriginHost: "192.168.1.2", Account: "1001", } cfg := config.NewDefaultCGRConfig() eCDR := &CDR{ ToR: utils.MetaVoice, RunID: utils.MetaDefault, Subject: "1001", RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: utils.Call, OriginID: "dsafdsaf", OriginHost: "192.168.1.2", Account: "1001", } cdr.AddDefaults(cfg) if !reflect.DeepEqual(cdr, eCDR) { t.Errorf("Expecting: %+v, received: %+v", eCDR, cdr) } } func TestNewCDRFromExternalCDRSetupTimeError(t *testing.T) { extCdr := &ExternalCDR{ // CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: "*testTime", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.MetaDefault, Usage: "10", Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } _, err := NewCDRFromExternalCDR(extCdr, "") if err == nil || err.Error() != "Unsupported time format" { t.Error(err) } } func TestNewCDRFromExternalCDRAnswerTimeError(t *testing.T) { extCdr := &ExternalCDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", AnswerTime: "*testTime", RunID: utils.MetaDefault, Usage: "10", Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } _, err := NewCDRFromExternalCDR(extCdr, "") if err == nil || err.Error() != "Unsupported time format" { t.Error(err) } } func TestNewCDRFromExternalCDRUsageError(t *testing.T) { extCdr := &ExternalCDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", RunID: utils.MetaDefault, Usage: "testUsage", Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } _, err := NewCDRFromExternalCDR(extCdr, "") if err == nil || err.Error() != `time: invalid duration "testUsage"` { t.Error(err) } } func TestCDRCloneNilCDR(t *testing.T) { var storCdr *CDR if clnStorCdr := storCdr.Clone(); !reflect.DeepEqual(storCdr, clnStorCdr) { t.Errorf("\nExpecting: %+v, \nreceived: %+v", storCdr, clnStorCdr) } } func TestAsExternalCDR(t *testing.T) { extCdr := &ExternalCDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.MetaDefault, Usage: "10ns", Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } eStorCdr := &CDR{ OrderID: 123, ToR: utils.MetaVoice, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, RunID: utils.MetaDefault, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: 10, Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } if eCDR := eStorCdr.AsExternalCDR(); err != nil { t.Error(err) } else if !reflect.DeepEqual(extCdr, eCDR) { t.Errorf("\nExpected: %+v, \nreceived: %+v", utils.ToJSON(extCdr), utils.ToJSON(eCDR)) } } func TestAsExternalCDRDefaultTOR(t *testing.T) { extCdr := &ExternalCDR{ OrderID: 123, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.MetaDefault, Usage: "10", Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } eStorCdr := &CDR{ OrderID: 123, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, RunID: utils.MetaDefault, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: 10, Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } if eCDR := eStorCdr.AsExternalCDR(); err != nil { t.Error(err) } else if !reflect.DeepEqual(extCdr, eCDR) { t.Errorf("\nExpected: %+v, \nreceived: %+v", utils.ToJSON(extCdr), utils.ToJSON(eCDR)) } } func TestCDRString(t *testing.T) { testCdr := &CDR{ OrderID: 123, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, RunID: utils.MetaDefault, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: 10, Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } mrsh, _ := json.Marshal(testCdr) expected := string(mrsh) result := testCdr.String() if !reflect.DeepEqual(result, expected) { t.Errorf("\nExpected <%+v>, \nreceived <%+v>", expected, result) } } func TestCDRAsCDRsql(t *testing.T) { cdr := &CDR{ OrderID: 123, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", Source: utils.UnitTest, RequestType: utils.MetaRated, RunID: utils.MetaDefault, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), Usage: 10, Cost: 1.01, PreRated: true, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, } cdrSQL := new(CDRsql) cdrSQL.RunID = cdr.RunID cdrSQL.OriginHost = cdr.OriginHost cdrSQL.Source = cdr.Source cdrSQL.OriginID = cdr.OriginID cdrSQL.TOR = cdr.ToR cdrSQL.RequestType = cdr.RequestType cdrSQL.Tenant = cdr.Tenant cdrSQL.Category = cdr.Category cdrSQL.Account = cdr.Account cdrSQL.Subject = cdr.Subject cdrSQL.Destination = cdr.Destination cdrSQL.SetupTime = cdr.SetupTime if !cdr.AnswerTime.IsZero() { cdrSQL.AnswerTime = utils.TimePointer(cdr.AnswerTime) } cdrSQL.Usage = cdr.Usage.Nanoseconds() cdrSQL.ExtraFields = utils.ToJSON(cdr.ExtraFields) cdrSQL.CostSource = cdr.CostSource cdrSQL.Cost = cdr.Cost cdrSQL.ExtraInfo = cdr.ExtraInfo result := cdr.AsCDRsql() cdrSQL.CreatedAt = result.CreatedAt if !reflect.DeepEqual(result, cdrSQL) { t.Errorf("\nExpected <%+v>, \nreceived <%+v>", utils.ToJSON(cdrSQL), utils.ToJSON(result)) } } func TestCDRGetID(t *testing.T) { uR := &UsageRecord{ RequestType: utils.MetaRated, Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", Usage: "10", } result := uR.GetID() expected := utils.Sha1(uR.ToR, uR.RequestType, uR.Tenant, uR.Category, uR.Account, uR.Subject, uR.Destination, uR.SetupTime, uR.AnswerTime, uR.Usage) if !reflect.DeepEqual(result, expected) { t.Errorf("\nExpected <%+v>, \nreceived <%+v>", utils.ToJSON(expected), utils.ToJSON(result)) } }