all tests pass

This commit is contained in:
Radu Ioan Fericean
2012-07-03 14:49:04 +03:00
parent 5dc5593d9b
commit 4dce1c216f
7 changed files with 41 additions and 29 deletions

View File

@@ -4,4 +4,6 @@ CUSTOMER_1,0,OUT,rif:from:tm,danb,STANDARD,2012-02-28T00:00:00Z
CUSTOMER_2,0,OUT,danb:87.139.12.167,danb,STANDARD,2012-01-01T00:00:00Z
CUSTOMER_1,0,OUT,danb,,PREMIUM,2012-01-01T00:00:00Z
vdf,0,OUT,rif,,EVENING,2012-01-01T00:00:00Z
vdf,0,OUT,rif,,EVENING,2012-02-28T00:00:00Z
vdf,0,OUT,rif,,EVENING,2012-02-28T00:00:00Z
vdf,0,OUT,minu,,EVENING,2012-01-01T00:00:00Z
vdf,0,OUT,minu,,EVENING,2012-02-28T00:00:00Z
1 Tenant TOR Direction Subject RatesFallbackSubject RatesTimingTag ActivationTime
4 CUSTOMER_2 0 OUT danb:87.139.12.167 danb STANDARD 2012-01-01T00:00:00Z
5 CUSTOMER_1 0 OUT danb PREMIUM 2012-01-01T00:00:00Z
6 vdf 0 OUT rif EVENING 2012-01-01T00:00:00Z
7 vdf 0 OUT rif EVENING 2012-02-28T00:00:00Z
8 vdf 0 OUT minu EVENING 2012-01-01T00:00:00Z
9 vdf 0 OUT minu EVENING 2012-02-28T00:00:00Z

View File

@@ -86,7 +86,7 @@ func logAction(ub *UserBalance, a *Action) (err error) {
}
func resetTriggersAction(ub *UserBalance, a *Action) (err error) {
ub.ResetActionTriggers()
ub.resetActionTriggers()
return
}

View File

@@ -178,7 +178,7 @@ func (cd *CallDescriptor) splitTimeSpan(firstSpan *TimeSpan) (timespans []*TimeS
timespans = append(timespans, firstSpan)
// split on (free) minute buckets
if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil {
_, bucketList := userBalance.getSecondsForPrefix(cd.Destination)
_, _, bucketList := userBalance.getSecondsForPrefix(cd.Destination)
for _, mb := range bucketList {
for i := 0; i < len(timespans); i++ {
if timespans[i].MinuteInfo != nil {
@@ -296,8 +296,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
if userBalance.Type == UB_TYPE_POSTPAID {
return -1, nil
} else {
availableCredit = userBalance.BalanceMap[CREDIT]
availableSeconds, _ = userBalance.getSecondsForPrefix(cd.Destination)
availableSeconds, availableCredit, _ = userBalance.getSecondsForPrefix(cd.Destination)
}
} else {
return cd.Amount, err
@@ -306,10 +305,9 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
if availableCredit == 0 {
return availableSeconds, nil
}
maxSessionSeconds := cd.Amount
for i := 0; i < 10; i++ {
maxDuration, _ := time.ParseDuration(fmt.Sprintf("%vs", maxSessionSeconds))
maxDuration, _ := time.ParseDuration(fmt.Sprintf("%vs", maxSessionSeconds-availableSeconds))
ts := &TimeSpan{TimeStart: now, TimeEnd: now.Add(maxDuration)}
timespans := cd.splitTimeSpan(ts)
@@ -320,6 +318,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) {
}
cost += ts.getCost(cd)
}
//log.Print(availableCredit, availableSeconds, cost)
if cost < availableCredit {
return maxSessionSeconds, nil
} else { //decrease the period by 10% and try again

View File

@@ -31,18 +31,27 @@ func init() {
}
func populateDB() {
ub := &UserBalance{
minu := &UserBalance{
Id: "OUT:vdf:minu",
Type: UB_TYPE_PREPAID,
/*BalanceMap: map[string]float64{
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)
broker := &UserBalance{
Id: "OUT:vdf:broker",
Type: UB_TYPE_PREPAID,
MinuteBuckets: []*MinuteBucket{
&MinuteBucket{Seconds: 20, DestinationId: "NAT", Weight: 10, Price: 1},
&MinuteBucket{Seconds: 100, DestinationId: "RET", Weight: 20},
},
}
storageGetter.SetUserBalance(broker)
storageGetter.SetUserBalance(minu)
}
func TestSplitSpans(t *testing.T) {
@@ -174,7 +183,7 @@ func TestMaxSessionTimeNoUserBalance(t *testing.T) {
}
func TestMaxSessionTimeWithUserBalance(t *testing.T) {
cd := &CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "minu", Destination: "0723", Amount: 5400}
cd := &CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "minu", Destination: "0723", Amount: 1000}
result, err := cd.GetMaxSessionTime()
expected := 300.0
if result != expected || err != nil {

View File

@@ -33,6 +33,7 @@ type MinuteBucket struct {
precision int
}
// Returns the available number of seconds for a specified credit
func (mb *MinuteBucket) GetSecondsForCredit(credit float64) (seconds float64) {
seconds = mb.Seconds
if mb.Price > 0 {
@@ -63,9 +64,3 @@ func (bs bucketsorter) Less(j, i int) bool {
func (bs bucketsorter) Sort() {
sort.Sort(bs)
}
func (ub *UserBalance) ResetActionTriggers() {
for _, at := range ub.ActionTriggers {
at.executed = false
}
}

View File

@@ -19,8 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package timespans
import (
// "log"
"sort"
// "log"
)
const (
@@ -68,7 +67,7 @@ func (a AmountTooBig) Error() string {
/*
Returns user's available minutes for the specified destination
*/
func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds float64, bucketList bucketsorter) {
func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds, credit float64, bucketList bucketsorter) {
if len(ub.MinuteBuckets) == 0 {
// log.Print("There are no minute buckets to check for user: ", ub.Id)
return
@@ -86,8 +85,8 @@ func (ub *UserBalance) getSecondsForPrefix(prefix string) (seconds float64, buck
}
}
}
sort.Sort(bucketList) // sorts the buckets according to priority, precision or price
credit := ub.BalanceMap[CREDIT]
bucketList.Sort() // sorts the buckets according to priority, precision or price
credit = ub.BalanceMap[CREDIT]
for _, mb := range bucketList {
s := mb.GetSecondsForCredit(credit)
credit -= s * mb.Price
@@ -112,7 +111,7 @@ If the amount is bigger than the sum of all seconds in the minute buckets than n
debited and an error will be returned.
*/
func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string) error {
avaliableNbSeconds, bucketList := ub.getSecondsForPrefix(prefix)
avaliableNbSeconds, _, bucketList := ub.getSecondsForPrefix(prefix)
if avaliableNbSeconds < amount {
return new(AmountTooBig)
}
@@ -139,6 +138,7 @@ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string) error
return new(AmountTooBig)
}
ub.BalanceMap[CREDIT] = credit // credit is > 0
for _, mb := range bucketList {
if mb.Seconds < amount {
amount -= mb.Seconds
@@ -182,6 +182,7 @@ func (ub *UserBalance) addMinuteBucket(newMb *MinuteBucket) {
}
}
// Scans the action trigers and execute the actions for which trigger is met
func (ub *UserBalance) executeActionTriggers() {
ub.ActionTriggers.Sort()
for _, at := range ub.ActionTriggers {
@@ -209,6 +210,13 @@ func (ub *UserBalance) executeActionTriggers() {
}
}
// Mark all action trigers as ready for execution
func (ub *UserBalance) resetActionTriggers() {
for _, at := range ub.ActionTriggers {
at.executed = false
}
}
/*
Adds the specified amount of seconds.
*/

View File

@@ -49,9 +49,9 @@ func TestGetSecondsForPrefix(t *testing.T) {
b1 := &MinuteBucket{Seconds: 10, Weight: 10, DestinationId: "NAT"}
b2 := &MinuteBucket{Seconds: 100, Weight: 20, DestinationId: "RET"}
ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 200}}
seconds, bucketList := ub1.getSecondsForPrefix("0723")
seconds, credit, bucketList := ub1.getSecondsForPrefix("0723")
expected := 110.0
if seconds != expected || bucketList[0].Weight < bucketList[1].Weight {
if credit != 200 || seconds != expected || bucketList[0].Weight < bucketList[1].Weight {
t.Errorf("Expected %v was %v", expected, seconds)
}
}
@@ -61,9 +61,9 @@ func TestGetPricedSeconds(t *testing.T) {
b2 := &MinuteBucket{Seconds: 100, Price: 1, Weight: 20, DestinationId: "RET"}
ub1 := &UserBalance{Id: "OUT:CUSTOMER_1:rif", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21}}
seconds, bucketList := ub1.getSecondsForPrefix("0723")
seconds, credit, bucketList := ub1.getSecondsForPrefix("0723")
expected := 21.0
if seconds != expected || bucketList[0].Weight < bucketList[1].Weight {
if credit != 0 || seconds != expected || bucketList[0].Weight < bucketList[1].Weight {
t.Errorf("Expected %v was %v", expected, seconds)
}
}
@@ -168,7 +168,6 @@ func TestDebitPriceMinuteBalance(t *testing.T) {
rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21}}
err := rifsBalance.debitMinutesBalance(5, "0723")
if b2.Seconds != 95 || b1.Seconds != 10 || err != nil || rifsBalance.BalanceMap[CREDIT] != 16 {
t.Log(rifsBalance.BalanceMap[CREDIT])
t.Errorf("Expected %v was %v", 16, rifsBalance.BalanceMap[CREDIT])
}
}