gob switch tests

This commit is contained in:
Radu Ioan Fericean
2012-02-29 14:07:03 +02:00
parent 2aa4cde569
commit a16a75d8e8
8 changed files with 100 additions and 171 deletions

View File

@@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package main
import (
"bytes"
//"encoding/gob"
"encoding/json"
"flag"
"github.com/rif/cgrates/timespans"
@@ -39,6 +41,27 @@ var (
ubfile = flag.String("ubfile", "ub.json", "User budgets file")
)
func testGob(key string, aps []*timespans.ActivationPeriod) {
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
dec := json.NewDecoder(&buf)
enc.Encode(aps)
result := buf.String()
aps1 := make([]*timespans.ActivationPeriod, 0)
buf.Reset()
buf.WriteString(result)
err := dec.Decode(&aps1)
log.Print("Err: ", err)
buf.Reset()
enc.Encode(aps1)
result1 := buf.String()
log.Print("Equal? ", result == result1, len(result), len(result1))
}
func writeToStorage(storage timespans.StorageGetter,
callDescriptors []*timespans.CallDescriptor,
destinations []*timespans.Destination,
@@ -47,6 +70,7 @@ func writeToStorage(storage timespans.StorageGetter,
for _, cd := range callDescriptors {
storage.SetActivationPeriods(cd.GetKey(), cd.ActivationPeriods)
log.Printf("Storing activation periods for %q", cd.GetKey())
testGob(cd.GetKey(), cd.ActivationPeriods)
}
for _, d := range destinations {
storage.SetDestination(d)
@@ -64,7 +88,6 @@ func writeToStorage(storage timespans.StorageGetter,
func main() {
flag.Parse()
log.Printf("Reading from %s, %s, %s", *apfile, *destfile, *tpfile)
// reading activation periods

View File

@@ -18,8 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package timespans
import (
"strconv"
"strings"
"time"
//"log"
)
@@ -40,57 +38,3 @@ func (ap *ActivationPeriod) AddInterval(is ...*Interval) {
ap.Intervals = append(ap.Intervals, i)
}
}
/*
Serializes the activation periods for the storage. Used for key-value storages.
*/
func (ap *ActivationPeriod) store() (result string) {
result += strconv.FormatInt(ap.ActivationTime.UnixNano(), 10) + ";"
for _, i := range ap.Intervals {
var is string
is = strconv.Itoa(int(i.Month)) + "|"
is += strconv.Itoa(i.MonthDay) + "|"
for _, wd := range i.WeekDays {
is += strconv.Itoa(int(wd)) + ","
}
is = strings.TrimRight(is, ",") + "|"
is += i.StartTime + "|"
is += i.EndTime + "|"
is += strconv.FormatFloat(i.Ponder, 'f', -1, 64) + "|"
is += strconv.FormatFloat(i.ConnectFee, 'f', -1, 64) + "|"
is += strconv.FormatFloat(i.Price, 'f', -1, 64) + "|"
is += strconv.FormatFloat(i.BillingUnit, 'f', -1, 64)
result += is + ";"
}
return
}
/*
De-serializes the activation periods for the storage. Used for key-value storages.
*/
func (ap *ActivationPeriod) restore(input string) {
elements := strings.Split(input, ";")
unixNano, _ := strconv.ParseInt(elements[0], 10, 64)
ap.ActivationTime = time.Unix(0, unixNano).In(time.UTC)
for _, is := range elements[1 : len(elements)-1] {
i := &Interval{}
ise := strings.Split(is, "|")
month, _ := strconv.Atoi(ise[0])
i.Month = time.Month(month)
i.MonthDay, _ = strconv.Atoi(ise[1])
for _, d := range strings.Split(ise[2], ",") {
if d != "" {
wd, _ := strconv.Atoi(d)
i.WeekDays = append(i.WeekDays, time.Weekday(wd))
}
}
i.StartTime = ise[3]
i.EndTime = ise[4]
i.Ponder, _ = strconv.ParseFloat(ise[5], 64)
i.ConnectFee, _ = strconv.ParseFloat(ise[6], 64)
i.Price, _ = strconv.ParseFloat(ise[7], 64)
i.BillingUnit, _ = strconv.ParseFloat(ise[8], 64)
ap.Intervals = append(ap.Intervals, i)
}
}

View File

@@ -19,64 +19,9 @@ package timespans
import (
"testing"
"time"
//"log"
)
func TestApStoreRestore(t *testing.T) {
d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC)
i := &Interval{Month: time.February,
MonthDay: 1,
WeekDays: []time.Weekday{time.Wednesday, time.Thursday},
StartTime: "14:30:00",
EndTime: "15:00:00"}
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;"
if result != expected {
t.Errorf("Expected %q was %q", expected, result)
}
ap1 := ActivationPeriod{}
ap1.restore(result)
if ap1.ActivationTime != ap.ActivationTime {
t.Errorf("Expected %v was %v", ap.ActivationTime, ap1.ActivationTime)
}
i1 := ap1.Intervals[0]
if i1.Month != i.Month {
t.Errorf("Expected %q was %q", i.Month, i1.Month)
}
if i1.MonthDay != i.MonthDay {
t.Errorf("Expected %q was %q", i.MonthDay, i1.MonthDay)
}
for j, wd := range i1.WeekDays {
if wd != i1.WeekDays[j] {
t.Errorf("Expected %q was %q", i.StartTime, i1.StartTime)
}
}
if i1.StartTime != i.StartTime {
t.Errorf("Expected %q was %q", i.StartTime, i1.StartTime)
}
if i1.EndTime != i.EndTime {
t.Errorf("Expected %q was %q", i.EndTime, i1.EndTime)
}
if i1.Ponder != i.Ponder {
t.Errorf("Expected %q was %q", i.Ponder, i1.Ponder)
}
if i1.ConnectFee != i.ConnectFee {
t.Errorf("Expected %q was %q", i.ConnectFee, i1.ConnectFee)
}
if i1.Price != i.Price {
t.Errorf("Expected %q was %q", i.Price, i1.Price)
}
if i1.BillingUnit != i.BillingUnit {
t.Errorf("Expected %q was %q", i.BillingUnit, i1.BillingUnit)
}
}
func BenchmarkActivationPeriodRestore(b *testing.B) {
ap := ActivationPeriod{}
for i := 0; i < b.N; i++ {
ap.restore("1328106601;2|1|3,4|14:30:00|15:00:00|0|0|0|0;")
}
}

View File

@@ -86,9 +86,9 @@ func (cd *CallDescriptor) SetStorageGetter(sg StorageGetter) {
}
/*
Restores the activation periods from storage.
Restores the activation periods for the specified prefix from storage.
*/
func (cd *CallDescriptor) RestoreFromStorage() (destPrefix string, err error) {
func (cd *CallDescriptor) SearchStorageForPrefix() (destPrefix string, err error) {
cd.ActivationPeriods = make([]*ActivationPeriod, 0)
base := fmt.Sprintf("%s:%s:", cd.CstmId, cd.Subject)
destPrefix = cd.DestinationPrefix
@@ -200,14 +200,14 @@ func (cd *CallDescriptor) splitTimeSpan(firstSpan *TimeSpan) (timespans []*TimeS
Creates a CallCost structure with the cost nformation calculated for the received CallDescriptor.
*/
func (cd *CallDescriptor) GetCost() (*CallCost, error) {
destPrefix, err := cd.RestoreFromStorage()
destPrefix, err := cd.SearchStorageForPrefix()
timespans := cd.splitInTimeSpans()
cost := 0.0
connectionFee := 0.0
for i, ts := range timespans {
if ts.MinuteInfo == nil && i == 0 {
if i == 0 && ts.MinuteInfo == nil && ts.Interval != nil {
connectionFee = ts.Interval.ConnectFee
}
cost += ts.GetCost(cd)
@@ -227,7 +227,7 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) {
Returns the cost of a second in the present time conditions.
*/
func (cd *CallDescriptor) getPresentSecondCost() (cost float64, err error) {
_, err = cd.RestoreFromStorage()
_, err = cd.SearchStorageForPrefix()
now := time.Now()
oneSecond, _ := time.ParseDuration("1s")
ts := &TimeSpan{TimeStart: now, TimeEnd: now.Add(oneSecond)}
@@ -245,7 +245,7 @@ and will decrease it by 10% for nine times. So if the user has little credit it
If the user has no credit then it will return 0.
*/
func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
_, err = cd.RestoreFromStorage()
_, err = cd.SearchStorageForPrefix()
now := time.Now()
availableCredit, availableSeconds := 0.0, 0.0
if userBudget, err := cd.getUserBudget(); err == nil && userBudget != nil {

View File

@@ -24,7 +24,7 @@ import (
)
func TestKyotoStoreRestore(t *testing.T) {
getter, _ := NewKyotoStorage("test.kch")
getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10)
defer getter.Close()
d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC)
i := &Interval{Month: time.February,
@@ -54,7 +54,7 @@ func TestKyotoSplitSpans(t *testing.T) {
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
cd.RestoreFromStorage()
cd.SearchStorageForPrefix()
timespans := cd.splitInTimeSpans()
if len(timespans) != 2 {
t.Log(cd.ActivationPeriods)
@@ -70,7 +70,7 @@ func TestRedisSplitSpans(t *testing.T) {
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
cd.RestoreFromStorage()
cd.SearchStorageForPrefix()
timespans := cd.splitInTimeSpans()
if len(timespans) != 2 {
t.Log(cd.ActivationPeriods)
@@ -136,6 +136,7 @@ func TestFullDestNotFound(t *testing.T) {
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", Cost: 540, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
t.Log(cd.ActivationPeriods)
t.Errorf("Expected %v was %v", expected, result)
}
}
@@ -150,8 +151,7 @@ func TestMultipleActivationPeriods(t *testing.T) {
result, _ := cd.GetCost()
expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0257", Cost: 330, ConnectFee: 0}
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
t.Log(result.Timespans[0].ActivationPeriod)
t.Log(result.Timespans[1].ActivationPeriod)
t.Log(result.Timespans)
t.Errorf("Expected %v was %v", expected, result)
}
}
@@ -298,7 +298,7 @@ func BenchmarkRedisRestoring(b *testing.B) {
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.RestoreFromStorage()
cd.SearchStorageForPrefix()
}
}
@@ -341,7 +341,7 @@ func BenchmarkKyotoRestoring(b *testing.B) {
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.RestoreFromStorage()
cd.SearchStorageForPrefix()
}
}
@@ -353,7 +353,7 @@ func BenchmarkSplitting(b *testing.B) {
t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC)
t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC)
cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2, storageGetter: getter}
cd.RestoreFromStorage()
cd.SearchStorageForPrefix()
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.splitInTimeSpans()

View File

@@ -18,45 +18,52 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package timespans
import (
"bytes"
"encoding/gob"
"github.com/fsouza/gokabinet/kc"
//"log"
"strings"
// "log"
"sync"
)
type KyotoStorage struct {
db *kc.DB
db *kc.DB
buf bytes.Buffer
enc *gob.Encoder
dec *gob.Decoder
mux sync.Mutex // we need norma lock because we reset the buf variable
}
func NewKyotoStorage(filaName string) (*KyotoStorage, error) {
ndb, err := kc.Open(filaName, kc.WRITE)
return &KyotoStorage{db: ndb}, err
ks := &KyotoStorage{db: ndb}
ks.enc = gob.NewEncoder(&ks.buf)
ks.dec = gob.NewDecoder(&ks.buf)
return ks, err
}
func (ks *KyotoStorage) Close() {
ks.db.Close()
}
func (ks *KyotoStorage) GetActivationPeriods(key string) (aps []*ActivationPeriod, err error) {
values, err := ks.db.Get(key)
func (ks *KyotoStorage) SetActivationPeriods(key string, aps []*ActivationPeriod) error {
ks.mux.Lock()
defer ks.mux.Unlock()
if err == nil {
for _, ap_string := range strings.Split(values, "\n") {
if len(ap_string) > 0 {
ap := &ActivationPeriod{}
ap.restore(ap_string)
aps = append(aps, ap)
}
}
}
return aps, err
ks.buf.Reset()
ks.enc.Encode(aps)
return ks.db.Set(key, ks.buf.String())
}
func (ks *KyotoStorage) SetActivationPeriods(key string, aps []*ActivationPeriod) error {
result := ""
for _, ap := range aps {
result += ap.store() + "\n"
}
return ks.db.Set(key, result)
func (ks *KyotoStorage) GetActivationPeriods(key string) (aps []*ActivationPeriod, err error) {
ks.mux.Lock()
defer ks.mux.Unlock()
values, err := ks.db.Get(key)
ks.buf.Reset()
ks.buf.WriteString(values)
ks.dec.Decode(&aps)
return
}
func (ks *KyotoStorage) GetDestination(key string) (dest *Destination, err error) {

View File

@@ -18,47 +18,57 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package timespans
import (
"bytes"
"encoding/gob"
"github.com/simonz05/godis"
"strings"
"log"
"sync"
)
type RedisStorage struct {
dbNb int
db *godis.Client
buf bytes.Buffer
enc *gob.Encoder
dec *gob.Decoder
mux sync.Mutex
}
func NewRedisStorage(address string, db int) (*RedisStorage, error) {
ndb := godis.New(address, db, "")
return &RedisStorage{db: ndb, dbNb: db}, nil
rs := &RedisStorage{db: ndb, dbNb: db}
rs.enc = gob.NewEncoder(&rs.buf)
rs.dec = gob.NewDecoder(&rs.buf)
return rs, nil
}
func (rs *RedisStorage) Close() {
rs.db.Quit()
}
func (rs *RedisStorage) GetActivationPeriods(key string) (aps []*ActivationPeriod, err error) {
//rs.db.Select(rs.dbNb)
elem, err := rs.db.Get(key)
values := elem.String()
if err == nil {
for _, ap_string := range strings.Split(values, "\n") {
if len(ap_string) > 0 {
ap := &ActivationPeriod{}
ap.restore(ap_string)
aps = append(aps, ap)
}
}
}
return aps, err
}
func (rs *RedisStorage) SetActivationPeriods(key string, aps []*ActivationPeriod) error {
//.db.Select(rs.dbNb)
result := ""
for _, ap := range aps {
result += ap.store() + "\n"
}
return rs.db.Set(key, result)
rs.mux.Lock()
defer rs.mux.Unlock()
rs.buf.Reset()
rs.enc.Encode(aps)
return rs.db.Set(key, rs.buf.Bytes())
}
func (rs *RedisStorage) GetActivationPeriods(key string) (aps []*ActivationPeriod, err error) {
//rs.db.Select(rs.dbNb)
rs.mux.Lock()
defer rs.mux.Unlock()
elem, err := rs.db.Get(key)
rs.buf.Reset()
rs.buf.Write(elem.Bytes())
e := rs.dec.Decode(&aps)
log.Print(e)
return
}
func (rs *RedisStorage) GetDestination(key string) (dest *Destination, err error) {

Binary file not shown.