/* 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 ( "reflect" "sort" "testing" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) var defaultTenant = "cgrates.org" func TestAlias2AtttributeProfile(t *testing.T) { aliases := map[int]*v1Alias{ 0: { Tenant: utils.MetaAny, Direction: utils.MetaOut, Category: utils.MetaAny, Account: utils.MetaAny, Subject: utils.MetaAny, Context: "*rating", Values: v1AliasValues{}, }, 1: { Tenant: utils.MetaAny, Direction: utils.MetaOut, Category: utils.MetaAny, Account: utils.MetaAny, Subject: utils.MetaAny, Context: "*rating", Values: v1AliasValues{ &v1AliasValue{ DestinationId: utils.MetaAny, Pairs: map[string]map[string]string{ "Account": { "1001": "1002", }, }, Weight: 20, }, }, }, 2: { Tenant: utils.MetaAny, Direction: utils.MetaOut, Category: utils.MetaAny, Account: utils.MetaAny, Subject: utils.MetaAny, Context: "*rating", Values: v1AliasValues{ &v1AliasValue{ DestinationId: utils.MetaAny, Pairs: map[string]map[string]string{ "Account": { "1001": "1002", "1003": "1004", }, }, Weight: 10, }, }, }, 3: { Tenant: "", Direction: "", Category: "", Account: "", Subject: "", Context: "", Values: v1AliasValues{ &v1AliasValue{ DestinationId: utils.MetaAny, Pairs: map[string]map[string]string{ "Account": { "1001": "1002", "1003": "1004", }, }, Weight: 10, }, }, }, 4: { Tenant: "notDefaultTenant", Direction: "*out", Category: "*voice", Account: "1001", Subject: utils.MetaAny, Context: "*rated", Values: v1AliasValues{ &v1AliasValue{ DestinationId: "DST_1003", Pairs: map[string]map[string]string{ "Account": { "": "1002", }, "Subject": { "": "call_1001", }, }, Weight: 10, }, }, }, 5: { Tenant: "notDefaultTenant", Direction: "*out", Category: utils.MetaAny, Account: "1001", Subject: "call_1001", Context: "*rated", Values: v1AliasValues{ &v1AliasValue{ DestinationId: "DST_1003", Pairs: map[string]map[string]string{ "Account": { "1001": "1002", }, "Category": { "call_1001": "call_1002", }, }, Weight: 10, }, }, }, 6: { Tenant: utils.MetaAny, Category: "somecateg_5141", Account: utils.MetaAny, Subject: utils.MetaAny, Context: "*rated", Values: v1AliasValues{ &v1AliasValue{ Pairs: map[string]map[string]string{ utils.Category: { "somecateg_5141": "somecateg_roam_fromz4", }, }, }, }, }, } expected := map[int]*engine.AttributeProfile{ 0: { Tenant: defaultTenant, ID: aliases[0].GetId(), Contexts: []string{utils.MetaAny}, FilterIDs: make([]string, 0), ActivationInterval: nil, Attributes: make([]*engine.Attribute, 0), Blocker: false, Weight: 20, }, 1: { Tenant: defaultTenant, ID: aliases[1].GetId(), Contexts: []string{utils.MetaAny}, FilterIDs: make([]string, 0), ActivationInterval: nil, Attributes: []*engine.Attribute{ { FilterIDs: []string{"*string:~*req.Account:1001"}, Path: utils.MetaReq + utils.NestingSep + "Account", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("1002", utils.InfieldSep), }, }, Blocker: false, Weight: 20, }, 2: { Tenant: defaultTenant, ID: aliases[2].GetId(), Contexts: []string{utils.MetaAny}, FilterIDs: make([]string, 0), ActivationInterval: nil, Attributes: []*engine.Attribute{ { FilterIDs: []string{"*string:~*req.Account:1001"}, Path: utils.MetaReq + utils.NestingSep + "Account", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("1002", utils.InfieldSep), }, { FilterIDs: []string{"*string:~*req.Account:1003"}, Path: utils.MetaReq + utils.NestingSep + "Account", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("1004", utils.InfieldSep), }, }, Blocker: false, Weight: 20, }, 3: { Tenant: defaultTenant, ID: aliases[3].GetId(), Contexts: []string{utils.MetaAny}, FilterIDs: make([]string, 0), ActivationInterval: nil, Attributes: []*engine.Attribute{ { FilterIDs: []string{"*string:~*req.Account:1001"}, Path: utils.MetaReq + utils.NestingSep + "Account", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("1002", utils.InfieldSep), }, { FilterIDs: []string{"*string:~*req.Account:1003"}, Path: utils.MetaReq + utils.NestingSep + "Account", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("1004", utils.InfieldSep), }, }, Blocker: false, Weight: 20, }, 4: { Tenant: "notDefaultTenant", ID: aliases[4].GetId(), Contexts: []string{utils.MetaAny}, FilterIDs: []string{ "*string:~*req.Category:*voice", "*string:~*req.Account:1001", "*destinations:~*req.Destination:DST_1003", }, ActivationInterval: nil, Attributes: []*engine.Attribute{ { Path: utils.MetaReq + utils.NestingSep + "Account", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("1002", utils.InfieldSep), }, { Path: utils.MetaReq + utils.NestingSep + "Subject", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("call_1001", utils.InfieldSep), }, }, Blocker: false, Weight: 20, }, 5: { Tenant: "notDefaultTenant", ID: aliases[5].GetId(), Contexts: []string{utils.MetaAny}, FilterIDs: []string{ "*string:~*req.Account:1001", "*string:~*req.Subject:call_1001", "*destinations:~*req.Destination:DST_1003", }, ActivationInterval: nil, Attributes: []*engine.Attribute{ { Path: utils.MetaReq + utils.NestingSep + "Account", Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("1002", utils.InfieldSep), }, { Path: utils.MetaReq + utils.NestingSep + "Category", Type: utils.MetaVariable, FilterIDs: []string{"*string:~*req.Category:call_1001"}, Value: config.NewRSRParsersMustCompile("call_1002", utils.InfieldSep), }, }, Blocker: false, Weight: 20, }, 6: { Tenant: "cgrates.org", ID: aliases[6].GetId(), Contexts: []string{utils.MetaAny}, FilterIDs: []string{ "*string:~*req.Category:somecateg_5141", }, Attributes: []*engine.Attribute{ { Path: utils.MetaReq + utils.NestingSep + utils.Category, Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("somecateg_roam_fromz4", utils.InfieldSep), }, }, Weight: 20, }, } for i := range expected { rply := alias2AtttributeProfile(aliases[i], defaultTenant) sort.Slice(rply.Attributes, func(i, j int) bool { if rply.Attributes[i].Path == rply.Attributes[j].Path { return rply.Attributes[i].FilterIDs[0] < rply.Attributes[j].FilterIDs[0] } return rply.Attributes[i].Path < rply.Attributes[j].Path }) // only for test; map returns random keys if !reflect.DeepEqual(expected[i], rply) { t.Errorf("For %v expected: %s ,received: %s ", i, utils.ToJSON(expected[i]), utils.ToJSON(rply)) } } } func TestV1AliasSetId(t *testing.T) { t.Run("valid id with 6 parts", func(t *testing.T) { alias := &v1Alias{} id := "dir:tenant:cat:acc:subj:ctx" err := alias.SetId(id) if err != nil { t.Fatalf("expected no error, got %v", err) } if alias.Direction != "dir" || alias.Tenant != "tenant" || alias.Category != "cat" || alias.Account != "acc" || alias.Subject != "subj" || alias.Context != "ctx" { t.Fatalf("fields not set correctly, got %+v", alias) } }) t.Run("invalid id with fewer than 6 parts", func(t *testing.T) { alias := &v1Alias{} id := "dir:tenant:cat:acc:subj" err := alias.SetId(id) if err == nil { t.Fatal("expected error, got nil") } if err != utils.ErrInvalidKey { t.Fatalf("expected %v, got %v", utils.ErrInvalidKey, err) } }) t.Run("invalid id with more than 6 parts", func(t *testing.T) { alias := &v1Alias{} id := "dir:tenant:cat:acc:subj:ctx:extra" err := alias.SetId(id) if err == nil { t.Fatal("expected error, got nil") } if err != utils.ErrInvalidKey { t.Fatalf("expected %v, got %v", utils.ErrInvalidKey, err) } }) }