mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-14 20:59:53 +05:00
MyMarshaler fully impelmented
This commit is contained in:
@@ -204,9 +204,9 @@ Serializes the action timing for the storage. Used for key-value storages.
|
||||
func (at *ActionTiming) store() (result string) {
|
||||
result += at.Tag + "|"
|
||||
for _, ubi := range at.UserBalanceIds {
|
||||
result += ubi + ";"
|
||||
result += ubi + ","
|
||||
}
|
||||
result = strings.TrimRight(result, ";") + "|"
|
||||
result = strings.TrimRight(result, ",") + "|"
|
||||
result += at.Timing.store() + "|"
|
||||
result += strconv.FormatFloat(at.Weight, 'f', -1, 64) + "|"
|
||||
result += at.ActionsId
|
||||
@@ -219,9 +219,10 @@ De-serializes the action timing for the storage. Used for key-value storages.
|
||||
func (at *ActionTiming) restore(input string) {
|
||||
elements := strings.Split(input, "|")
|
||||
at.Tag = elements[0]
|
||||
for _, ubi := range strings.Split(elements[1], ";") {
|
||||
for _, ubi := range strings.Split(elements[1], ",") {
|
||||
at.UserBalanceIds = append(at.UserBalanceIds, ubi)
|
||||
}
|
||||
|
||||
at.Timing = &Interval{}
|
||||
at.Timing.restore(elements[2])
|
||||
at.Weight, _ = strconv.ParseFloat(elements[3], 64)
|
||||
|
||||
@@ -21,6 +21,8 @@ package timespans
|
||||
import (
|
||||
"log"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ActionTrigger struct {
|
||||
@@ -73,3 +75,30 @@ func (atpl ActionTriggerPriotityList) Less(i, j int) bool {
|
||||
func (atpl ActionTriggerPriotityList) Sort() {
|
||||
sort.Sort(atpl)
|
||||
}
|
||||
|
||||
/*
|
||||
Serializes the action trigger for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (at *ActionTrigger) store() (result string) {
|
||||
result += at.BalanceId + ";"
|
||||
result += at.DestinationId + ";"
|
||||
result += at.ActionsId + ";"
|
||||
result += strconv.FormatFloat(at.ThresholdValue, 'f', -1, 64) + ";"
|
||||
result += strconv.FormatFloat(at.Weight, 'f', -1, 64)
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
De-serializes the action timing for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (at *ActionTrigger) restore(input string) {
|
||||
elements := strings.Split(input, ";")
|
||||
if len(elements) != 5 {
|
||||
return
|
||||
}
|
||||
at.BalanceId = elements[0]
|
||||
at.DestinationId = elements[1]
|
||||
at.ActionsId = elements[2]
|
||||
at.ThresholdValue, _ = strconv.ParseFloat(elements[3], 64)
|
||||
at.Weight, _ = strconv.ParseFloat(elements[4], 64)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func TestActionTimingStoreRestore(t *testing.T) {
|
||||
ActionsId: "Commando",
|
||||
}
|
||||
r := at.store()
|
||||
if string(r) != "test|one;two;three|1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;1|10|Commando" {
|
||||
if string(r) != "test|one,two,three|1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5;18:00:00;00:00:00;10;0;1;1|10|Commando" {
|
||||
t.Errorf("Error serializing action timing: %v", string(r))
|
||||
}
|
||||
o := &ActionTiming{}
|
||||
@@ -54,6 +54,25 @@ func TestActionTimingStoreRestore(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionTriggerStoreRestore(t *testing.T) {
|
||||
at := &ActionTrigger{
|
||||
BalanceId: CREDIT,
|
||||
ThresholdValue: 100.0,
|
||||
DestinationId: "NAT",
|
||||
Weight: 10.0,
|
||||
ActionsId: "Commando",
|
||||
}
|
||||
r := at.store()
|
||||
if string(r) != "MONETARY;NAT;Commando;100;10" {
|
||||
t.Errorf("Error serializing action trigger: %v", string(r))
|
||||
}
|
||||
o := &ActionTrigger{}
|
||||
o.restore(r)
|
||||
if !reflect.DeepEqual(o, at) {
|
||||
t.Errorf("Expected %v was %v", at, o)
|
||||
}
|
||||
}
|
||||
|
||||
func TestActionTimingNothing(t *testing.T) {
|
||||
at := &ActionTiming{}
|
||||
st := at.GetNextStartTime()
|
||||
|
||||
@@ -69,6 +69,7 @@ func (ap *ActivationPeriod) store() (result string) {
|
||||
for _, i := range ap.Intervals {
|
||||
result += i.store() + "|"
|
||||
}
|
||||
result = strings.TrimRight(result, "|")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestApStoreRestore(t *testing.T) {
|
||||
ap := &ActivationPeriod{ActivationTime: d}
|
||||
ap.AddInterval(i)
|
||||
result := ap.store()
|
||||
expected := "1328106601000000000|2;1;3,4;14:30:00;15:00:00;0;0;0;0|"
|
||||
expected := "1328106601000000000|2;1;3,4;14:30:00;15:00:00;0;0;0;0"
|
||||
if result != expected {
|
||||
t.Errorf("Expected %q was %q", expected, result)
|
||||
}
|
||||
@@ -166,14 +166,7 @@ func TestApAddIntervalIfNotPresent(t *testing.T) {
|
||||
|
||||
/**************************** Benchmarks *************************************/
|
||||
|
||||
func BenchmarkActivationPeriodRestore(b *testing.B) {
|
||||
ap := ActivationPeriod{}
|
||||
for i := 0; i < b.N; i++ {
|
||||
json.Unmarshal([]byte("1328106601;2|1|3,4|14:30:00|15:00:00|0|0|0|0;"), &ap)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkActivationPeriodStoreRestore(b *testing.B) {
|
||||
func BenchmarkActivationPeriodStoreRestoreJson(b *testing.B) {
|
||||
b.StopTimer()
|
||||
d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC)
|
||||
i := &Interval{Months: []time.Month{time.February},
|
||||
@@ -191,3 +184,29 @@ func BenchmarkActivationPeriodStoreRestore(b *testing.B) {
|
||||
json.Unmarshal(result, &ap1)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkActivationPeriodRestore(b *testing.B) {
|
||||
ap := ActivationPeriod{}
|
||||
for i := 0; i < b.N; i++ {
|
||||
ap.restore("1328106601000000000|2;1;3,4;14:30:00;15:00:00;0;0;0;0")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkActivationPeriodStoreRestore(b *testing.B) {
|
||||
b.StopTimer()
|
||||
d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC)
|
||||
i := &Interval{Months: []time.Month{time.February},
|
||||
MonthDays: []int{1},
|
||||
WeekDays: []time.Weekday{time.Wednesday, time.Thursday},
|
||||
StartTime: "14:30:00",
|
||||
EndTime: "15:00:00"}
|
||||
ap := &ActivationPeriod{ActivationTime: d}
|
||||
ap.AddInterval(i)
|
||||
|
||||
ap1 := ActivationPeriod{}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result := ap.store()
|
||||
ap1.restore(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -194,6 +195,7 @@ func (mm *MyMarshaler) Unmarshal(data []byte, v interface{}) (err error) {
|
||||
return nil
|
||||
|
||||
}
|
||||
log.Print("Using default gob marshalling!")
|
||||
mm.buf.Reset()
|
||||
mm.buf.Write(data)
|
||||
return gob.NewDecoder(&mm.buf).Decode(v)
|
||||
|
||||
82
timespans/units_counter.go
Normal file
82
timespans/units_counter.go
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Rating system designed to be used in VoIP Carriers World
|
||||
Copyright (C) 2012 Radu Ioan Fericean
|
||||
|
||||
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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package timespans
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Amount of a trafic of a certain type
|
||||
type UnitsCounter struct {
|
||||
Direction string
|
||||
BalanceId string
|
||||
Units float64
|
||||
Weight float64
|
||||
MinuteBuckets []*MinuteBucket
|
||||
}
|
||||
|
||||
// Structure to store actions according to weight
|
||||
type countersorter []*UnitsCounter
|
||||
|
||||
func (s countersorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s countersorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s countersorter) Less(i, j int) bool {
|
||||
return s[i].Weight < s[j].Weight
|
||||
}
|
||||
|
||||
/*
|
||||
Serializes the unit counter for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (uc *UnitsCounter) store() (result string) {
|
||||
result += uc.Direction + "/"
|
||||
result += uc.BalanceId + "/"
|
||||
result += strconv.FormatFloat(uc.Units, 'f', -1, 64) + "/"
|
||||
result += strconv.FormatFloat(uc.Weight, 'f', -1, 64) + "/"
|
||||
for _, mb := range uc.MinuteBuckets {
|
||||
result += mb.store() + ","
|
||||
}
|
||||
result = strings.TrimRight(result, ",")
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
De-serializes the unit counter for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (uc *UnitsCounter) restore(input string) {
|
||||
elements := strings.Split(input, "/")
|
||||
if len(elements) != 5 {
|
||||
return
|
||||
}
|
||||
uc.Direction = elements[0]
|
||||
uc.BalanceId = elements[1]
|
||||
uc.Units, _ = strconv.ParseFloat(elements[2], 64)
|
||||
uc.Weight, _ = strconv.ParseFloat(elements[3], 64)
|
||||
for _, mbs := range strings.Split(elements[4], ",") {
|
||||
mb := &MinuteBucket{}
|
||||
mb.restore(mbs)
|
||||
uc.MinuteBuckets = append(uc.MinuteBuckets, mb)
|
||||
}
|
||||
}
|
||||
43
timespans/units_counter_test.go
Normal file
43
timespans/units_counter_test.go
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Rating system designed to be used in VoIP Carriers World
|
||||
Copyright (C) 2012 Radu Ioan Fericean
|
||||
|
||||
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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package timespans
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnitsCounterStoreRestore(t *testing.T) {
|
||||
uc := &UnitsCounter{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Units: 100,
|
||||
Weight: 10,
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, Percent: 0, DestinationId: "RET"}},
|
||||
}
|
||||
r := uc.store()
|
||||
if string(r) != "OUT/SMS/100/10/0;20;1;0;NAT,0;10;10;0;RET" {
|
||||
t.Errorf("Error serializing units counter: %v", string(r))
|
||||
}
|
||||
o := &UnitsCounter{}
|
||||
o.restore(r)
|
||||
if !reflect.DeepEqual(o, uc) {
|
||||
t.Errorf("Expected %v was %v", uc, o)
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package timespans
|
||||
|
||||
import (
|
||||
// "log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -291,26 +292,72 @@ Resets the user balance items to their tariff plan values.
|
||||
return
|
||||
}
|
||||
*/
|
||||
// Amount of a trafic of a certain type
|
||||
type UnitsCounter struct {
|
||||
Direction string
|
||||
BalanceId string
|
||||
Units float64
|
||||
Weight float64
|
||||
MinuteBuckets []*MinuteBucket
|
||||
|
||||
/*
|
||||
Serializes the user balance for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (ub *UserBalance) store() (result string) {
|
||||
result += ub.Id + "|"
|
||||
result += ub.Type + "|"
|
||||
for k, v := range ub.BalanceMap {
|
||||
result += k + ":" + strconv.FormatFloat(v, 'f', -1, 64) + "#"
|
||||
}
|
||||
result = strings.TrimRight(result, "#") + "|"
|
||||
for _, mb := range ub.MinuteBuckets {
|
||||
result += mb.store() + "#"
|
||||
}
|
||||
result = strings.TrimRight(result, "#") + "|"
|
||||
for _, uc := range ub.UnitCounters {
|
||||
result += uc.store() + "#"
|
||||
}
|
||||
result = strings.TrimRight(result, "#") + "|"
|
||||
for _, at := range ub.ActionTriggers {
|
||||
result += at.store() + "#"
|
||||
}
|
||||
result = strings.TrimRight(result, "#")
|
||||
return
|
||||
}
|
||||
|
||||
// Structure to store actions according to weight
|
||||
type countersorter []*UnitsCounter
|
||||
|
||||
func (s countersorter) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s countersorter) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s countersorter) Less(i, j int) bool {
|
||||
return s[i].Weight < s[j].Weight
|
||||
/*
|
||||
De-serializes the user balance for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (ub *UserBalance) restore(input string) {
|
||||
elements := strings.Split(input, "|")
|
||||
ub.Id = elements[0]
|
||||
ub.Type = elements[1]
|
||||
if ub.BalanceMap == nil {
|
||||
ub.BalanceMap = make(map[string]float64, 0)
|
||||
}
|
||||
for _, maps := range strings.Split(elements[2], "#") {
|
||||
kv := strings.Split(maps, ":")
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
value, _ := strconv.ParseFloat(kv[1], 64)
|
||||
ub.BalanceMap[kv[0]] = value
|
||||
}
|
||||
for _, mbs := range strings.Split(elements[3], "#") {
|
||||
if mbs == "" {
|
||||
continue
|
||||
}
|
||||
mb := &MinuteBucket{}
|
||||
mb.restore(mbs)
|
||||
ub.MinuteBuckets = append(ub.MinuteBuckets, mb)
|
||||
}
|
||||
for _, ucs := range strings.Split(elements[4], "#") {
|
||||
if ucs == "" {
|
||||
continue
|
||||
}
|
||||
uc := &UnitsCounter{}
|
||||
uc.restore(ucs)
|
||||
ub.UnitCounters = append(ub.UnitCounters, uc)
|
||||
}
|
||||
for _, ats := range strings.Split(elements[5], "#") {
|
||||
if ats == "" {
|
||||
continue
|
||||
}
|
||||
at := &ActionTrigger{}
|
||||
at.restore(ats)
|
||||
ub.ActionTriggers = append(ub.ActionTriggers, at)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,41 @@ func init() {
|
||||
}
|
||||
|
||||
func TestUserBalanceStoreRestore(t *testing.T) {
|
||||
uc := &UnitsCounter{
|
||||
Direction: OUTBOUND,
|
||||
BalanceId: SMS,
|
||||
Units: 100,
|
||||
Weight: 10,
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, Percent: 0, DestinationId: "RET"}},
|
||||
}
|
||||
at := &ActionTrigger{
|
||||
BalanceId: CREDIT,
|
||||
ThresholdValue: 100.0,
|
||||
DestinationId: "NAT",
|
||||
Weight: 10.0,
|
||||
ActionsId: "Commando",
|
||||
}
|
||||
ub := &UserBalance{
|
||||
Id: "rif",
|
||||
Type: UB_TYPE_POSTPAID,
|
||||
BalanceMap: map[string]float64{SMS: 14, TRAFFIC: 1024},
|
||||
MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, Percent: 0, DestinationId: "RET"}},
|
||||
UnitCounters: []*UnitsCounter{uc, uc},
|
||||
ActionTriggers: ActionTriggerPriotityList{at, at, at},
|
||||
}
|
||||
r := ub.store()
|
||||
if string(r) != "rif|postpaid|SMS:14#INTERNET:1024|0;20;1;0;NAT#0;10;10;0;RET|OUT/SMS/100/10/0;20;1;0;NAT,0;10;10;0;RET#OUT/SMS/100/10/0;20;1;0;NAT,0;10;10;0;RET|MONETARY;NAT;Commando;100;10#MONETARY;NAT;Commando;100;10#MONETARY;NAT;Commando;100;10" &&
|
||||
string(r) != "rif|postpaid|INTERNET:1024#SMS:14|0;20;1;0;NAT#0;10;10;0;RET|OUT/SMS/100/10/0;20;1;0;NAT,0;10;10;0;RET#OUT/SMS/100/10/0;20;1;0;NAT,0;10;10;0;RET|MONETARY;NAT;Commando;100;10#MONETARY;NAT;Commando;100;10#MONETARY;NAT;Commando;100;10" {
|
||||
t.Errorf("Error serializing action timing: %v", string(r))
|
||||
}
|
||||
o := &UserBalance{}
|
||||
o.restore(r)
|
||||
if !reflect.DeepEqual(o, ub) {
|
||||
t.Errorf("Expected %v was %v", ub, o)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserBalanceStorageStoreRestore(t *testing.T) {
|
||||
b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.01, DestinationId: "NAT"}
|
||||
b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"}
|
||||
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21}}
|
||||
|
||||
Reference in New Issue
Block a user