initial user budgets for test

This commit is contained in:
Radu Ioan Fericean
2012-07-03 13:27:48 +03:00
parent 85282b8177
commit 5dc5593d9b
8 changed files with 167 additions and 49 deletions

View File

@@ -76,6 +76,7 @@ var (
"TOPUP_RESET": topupResetAction,
"TOPUP": topupAction,
"DEBIT": debitAction,
"RESET_COUNTERS": resetCountersAction,
}
)
@@ -130,6 +131,11 @@ func debitAction(ub *UserBalance, a *Action) (err error) {
return
}
func resetCountersAction(ub *UserBalance, a *Action) (err error) {
//ub.UnitsCounters
return
}
type ActionTrigger struct {
BalanceId string
ThresholdValue float64

View File

@@ -24,13 +24,25 @@ import (
//"log"
)
var (
getter StorageGetter
)
func init() {
getter, _ = NewRedisStorage("tcp:127.0.0.1:6379", 10)
SetStorageGetter(getter)
storageGetter, _ = NewRedisStorage("tcp:127.0.0.1:6379", 10)
SetStorageGetter(storageGetter)
populateDB()
}
func populateDB() {
ub := &UserBalance{
Id: "OUT:vdf:minu",
Type: UB_TYPE_PREPAID,
/*BalanceMap: map[string]float64{
CREDIT: 21,
},*/
MinuteBuckets: []*MinuteBucket{
&MinuteBucket{Seconds: 200, DestinationId: "NAT", Weight: 10},
&MinuteBucket{Seconds: 100, DestinationId: "RET", Weight: 20},
},
}
storageGetter.SetUserBalance(ub)
}
func TestSplitSpans(t *testing.T) {
@@ -162,9 +174,9 @@ func TestMaxSessionTimeNoUserBalance(t *testing.T) {
}
func TestMaxSessionTimeWithUserBalance(t *testing.T) {
cd := &CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "minitsboy", Destination: "0723", Amount: 5400}
cd := &CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "minu", Destination: "0723", Amount: 5400}
result, err := cd.GetMaxSessionTime()
expected := 200.0
expected := 300.0
if result != expected || err != nil {
t.Errorf("Expected %v was %v", expected, result)
}
@@ -179,8 +191,8 @@ func TestMaxSessionTimeNoCredit(t *testing.T) {
}
/*func TestGetCostWithVolumeDiscount(t *testing.T) {
getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10)
defer getter.Close()
storageGetter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10)
defer storageGetter.Close()
vd1 := &VolumeDiscount{100, 10}
vd2 := &VolumeDiscount{500, 20}
seara := &TariffPlan{Id: "seara", SmsCredit: 100, VolumeDiscountThresholds: []*VolumeDiscount{vd1, vd2}}
@@ -219,7 +231,7 @@ func BenchmarkRedisGetting(b *testing.B) {
cd := &CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2}
b.StartTimer()
for i := 0; i < b.N; i++ {
getter.GetActivationPeriodsOrFallback(cd.GetKey())
storageGetter.GetActivationPeriodsOrFallback(cd.GetKey())
}
}

View File

@@ -32,6 +32,17 @@ var (
DestinationCacheMap = make(destinationCacheMap)
)
func GetDestination(dId string) (d *Destination, err error) {
d, exists := DestinationCacheMap[dId]
if !exists {
d, err = storageGetter.GetDestination(dId)
if err == nil && d != nil {
DestinationCacheMap[dId] = d
}
}
return
}
/*
De-serializes the destination for the storage. Used for key-value storages.
*/

View File

@@ -58,6 +58,34 @@ func TestDestinationContainsPrefix(t *testing.T) {
}
func TestDestinationGetExists(t *testing.T) {
d, err := GetDestination("NAT")
if err != nil || d == nil {
t.Error("Could not get destination: ", d)
}
}
func TestDestinationGetExistsCache(t *testing.T) {
GetDestination("NAT")
if _, exists := DestinationCacheMap["NAT"]; !exists {
t.Error("Destination not cached!")
}
}
func TestDestinationGetNotExists(t *testing.T) {
d, err := GetDestination("not existing")
if d != nil {
t.Error("Got false destination: ", err)
}
}
func TestDestinationGetNotExistsCache(t *testing.T) {
GetDestination("not existing")
if _, exists := DestinationCacheMap["not existing"]; exists {
t.Error("Bad destination cached")
}
}
/********************************* Benchmarks **********************************/
func BenchmarkDestinationRedisStoreRestore(b *testing.B) {

View File

@@ -20,6 +20,7 @@ package timespans
import (
// "log"
"sort"
"math"
)
@@ -39,3 +40,32 @@ func (mb *MinuteBucket) GetSecondsForCredit(credit float64) (seconds float64) {
}
return
}
/*
Structure to store minute buckets according to weight, precision or price.
*/
type bucketsorter []*MinuteBucket
func (bs bucketsorter) Len() int {
return len(bs)
}
func (bs bucketsorter) Swap(i, j int) {
bs[i], bs[j] = bs[j], bs[i]
}
func (bs bucketsorter) Less(j, i int) bool {
return bs[i].Weight < bs[j].Weight ||
bs[i].precision < bs[j].precision ||
bs[i].Price > bs[j].Price
}
func (bs bucketsorter) Sort() {
sort.Sort(bs)
}
func (ub *UserBalance) ResetActionTriggers() {
for _, at := range ub.ActionTriggers {
at.executed = false
}
}

View File

@@ -0,0 +1,56 @@
/*
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 (
"testing"
)
func TestMinutBucketSortWeight(t *testing.T) {
mb1 := &MinuteBucket{Weight: 1, precision: 2, Price: 2}
mb2 := &MinuteBucket{Weight: 2, precision: 1, Price: 1}
var bs bucketsorter
bs = append(bs, mb2, mb1)
bs.Sort()
if bs[0] != mb1 || bs[1] != mb2 {
t.Error("Buckets not sorted by weight!")
}
}
func TestMinutBucketSortPrecision(t *testing.T) {
mb1 := &MinuteBucket{Weight: 1, precision: 2, Price: 2}
mb2 := &MinuteBucket{Weight: 1, precision: 1, Price: 1}
var bs bucketsorter
bs = append(bs, mb2, mb1)
bs.Sort()
if bs[0] != mb1 || bs[1] != mb2 {
t.Error("Buckets not sorted by precision!")
}
}
func TestMinutBucketSortPrice(t *testing.T) {
mb1 := &MinuteBucket{Weight: 1, precision: 1, Price: 1}
mb2 := &MinuteBucket{Weight: 1, precision: 1, Price: 2}
var bs bucketsorter
bs = append(bs, mb2, mb1)
bs.Sort()
if bs[0] != mb1 || bs[1] != mb2 {
t.Error("Buckets not sorted by price!")
}
}

View File

@@ -65,31 +65,6 @@ func (a AmountTooBig) Error() string {
return "Amount excedes balance!"
}
/*
Structure to store minute buckets according to weight, precision or price.
*/
type bucketsorter []*MinuteBucket
func (bs bucketsorter) Len() int {
return len(bs)
}
func (bs bucketsorter) Swap(i, j int) {
bs[i], bs[j] = bs[j], bs[i]
}
func (bs bucketsorter) Less(j, i int) bool {
return bs[i].Weight < bs[j].Weight ||
bs[i].precision < bs[j].precision ||
bs[i].Price > bs[j].Price
}
func (ub *UserBalance) ResetActionTriggers() {
for _, at := range ub.ActionTriggers {
at.executed = false
}
}
/*
Returns user's available minutes for the specified destination
*/
@@ -99,8 +74,8 @@ func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds float64, buck
return
}
for _, mb := range ub.MinuteBuckets {
d, exists := DestinationCacheMap[mb.DestinationId]
if !exists {
d, err := GetDestination(mb.DestinationId)
if err != nil {
continue
}
contains, precision := d.containsPrefix(prefix)
@@ -207,7 +182,7 @@ func (ub *UserBalance) addMinuteBucket(newMb *MinuteBucket) {
}
}
func (ub *UserBalance) ExecuteActionTriggers() {
func (ub *UserBalance) executeActionTriggers() {
ub.ActionTriggers.Sort()
for _, at := range ub.ActionTriggers {
if at.executed {

View File

@@ -30,16 +30,16 @@ var (
)
func init() {
getter, _ = NewRedisStorage("tcp:127.0.0.1:6379", 10)
SetStorageGetter(getter)
storageGetter, _ = NewRedisStorage("tcp:127.0.0.1:6379", 10)
SetStorageGetter(storageGetter)
}
func TestUserBalanceStoreRestore(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}}
getter.SetUserBalance(rifsBalance)
ub1, err := getter.GetUserBalance("other")
storageGetter.SetUserBalance(rifsBalance)
ub1, err := storageGetter.GetUserBalance("other")
if err != nil || ub1.BalanceMap[CREDIT] != rifsBalance.BalanceMap[CREDIT] {
t.Errorf("Expected %v was %v", rifsBalance.BalanceMap[CREDIT], ub1.BalanceMap[CREDIT])
}
@@ -72,8 +72,8 @@ func TestUserBalanceRedisStore(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}}
getter.SetUserBalance(rifsBalance)
result, _ := getter.GetUserBalance(rifsBalance.Id)
storageGetter.SetUserBalance(rifsBalance)
result, _ := storageGetter.GetUserBalance(rifsBalance.Id)
if !reflect.DeepEqual(rifsBalance, result) {
t.Errorf("Expected %v was %v", rifsBalance, result)
}
@@ -261,7 +261,7 @@ func TestDebitNegativeSMSBalance(t *testing.T) {
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}}
rifsBalance.MinuteBuckets[0].Seconds, rifsBalance.MinuteBuckets[1].Seconds = 0.0, 0.0
err := rifsBalance.resetUserBalance(getter)
err := rifsBalance.resetUserBalance(storageGetter)
if err != nil ||
rifsBalance.MinuteBuckets[0] == b1 ||
rifsBalance.BalanceMap[SMS] != seara.SmsCredit {
@@ -307,7 +307,7 @@ func TestGetVolumeDiscountSteps(t *testing.T) {
func TestRecivedCallsBonus(t *testing.T) {
_ := NewKyotoStorage("../data/test.kch")
defer getter.Close()
defer storageGetter.Close()
rcb := &RecivedCallBonus{Credit: 100}
seara := &TariffPlan{Id: "seara_voo", SmsCredit: 100, ReceivedCallSecondsLimit: 10, RecivedCallBonus: rcb}
rifsBalance := &UserBalance{Id: "other", BalanceMap: map[string]float64{CREDIT: 21}, tariffPlan: seara, ReceivedCallSeconds: 1}
@@ -355,8 +355,8 @@ func BenchmarkUserBalanceRedisStoreRestore(b *testing.B) {
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}}
for i := 0; i < b.N; i++ {
getter.SetUserBalance(rifsBalance)
getter.GetUserBalance(rifsBalance.Id)
storageGetter.SetUserBalance(rifsBalance)
storageGetter.GetUserBalance(rifsBalance.Id)
}
}