mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 10:06:24 +05:00
Guardian test improvements to avoid race, parallel debit tests for calldesc
This commit is contained in:
@@ -20,6 +20,7 @@ package engine
|
||||
import (
|
||||
"log"
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -114,6 +115,100 @@ func populateDB() {
|
||||
}
|
||||
}
|
||||
|
||||
func debitTest(t *testing.T, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
t1 := time.Date(2017, time.February, 2, 17, 30, 0, 0, time.UTC)
|
||||
t2 := time.Date(2017, time.February, 2, 17, 30, 59, 0, time.UTC)
|
||||
cd := &CallDescriptor{Direction: "*out", Category: "call", Tenant: "cgrates.org", Account: "moneyp", Subject: "nt", Destination: "49", TimeStart: t1, TimeEnd: t2, LoopIndex: 0}
|
||||
_, err := cd.Debit()
|
||||
if err != nil {
|
||||
t.Errorf("Error debiting balance: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParallelDebit(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
moneyConcurent := &Account{
|
||||
ID: "cgrates.org:moneyp",
|
||||
BalanceMap: map[string]Balances{
|
||||
utils.MONETARY: Balances{
|
||||
&Balance{Value: 10000, Weight: 10},
|
||||
}},
|
||||
}
|
||||
if accountingStorage != nil && ratingStorage != nil {
|
||||
accountingStorage.SetAccount(moneyConcurent)
|
||||
} else {
|
||||
t.Log("Could not connect to db!")
|
||||
return
|
||||
}
|
||||
debitsToDo := 50
|
||||
for i := 0; i < debitsToDo; i++ {
|
||||
wg.Add(1)
|
||||
go debitTest(t, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
t1 := time.Date(2017, time.February, 2, 17, 30, 0, 0, time.UTC)
|
||||
t2 := time.Date(2017, time.February, 2, 17, 30, 59, 0, time.UTC)
|
||||
cd := &CallDescriptor{Direction: "*out", Category: "call", Tenant: "cgrates.org", Account: "moneyp", Subject: "nt", Destination: "49", TimeStart: t1, TimeEnd: t2, LoopIndex: 0}
|
||||
|
||||
acc, err := cd.getAccount()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error debiting balance: %+v", err)
|
||||
}
|
||||
if acc.BalanceMap[utils.MONETARY][0].GetValue() != float64(10000-(debitsToDo*60)) {
|
||||
t.Errorf("Balance does not match: %f, expected %f", acc.BalanceMap[utils.MONETARY][0].GetValue(), float64(10000-(debitsToDo*60)))
|
||||
}
|
||||
/*
|
||||
out, err := json.Marshal(acc)
|
||||
if err == nil {
|
||||
t.Log("Account: %s", string(out))
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
func TestSerialDebit(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
moneyConcurent := &Account{
|
||||
ID: "cgrates.org:moneyp",
|
||||
BalanceMap: map[string]Balances{
|
||||
utils.MONETARY: Balances{
|
||||
&Balance{Value: 10000, Weight: 10},
|
||||
}},
|
||||
}
|
||||
if accountingStorage != nil && ratingStorage != nil {
|
||||
accountingStorage.SetAccount(moneyConcurent)
|
||||
} else {
|
||||
t.Log("Could not connect to db!")
|
||||
return
|
||||
}
|
||||
debitsToDo := 50
|
||||
for i := 0; i < debitsToDo; i++ {
|
||||
wg.Add(1)
|
||||
debitTest(t, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
t1 := time.Date(2017, time.February, 2, 17, 30, 0, 0, time.UTC)
|
||||
t2 := time.Date(2017, time.February, 2, 17, 30, 59, 0, time.UTC)
|
||||
cd := &CallDescriptor{Direction: "*out", Category: "call", Tenant: "cgrates.org", Account: "moneyp", Subject: "nt", Destination: "49", TimeStart: t1, TimeEnd: t2, LoopIndex: 0}
|
||||
|
||||
acc, err := cd.getAccount()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error debiting balance: %+v", err)
|
||||
}
|
||||
if acc.BalanceMap[utils.MONETARY][0].GetValue() != float64(10000-(debitsToDo*60)) {
|
||||
t.Errorf("Balance does not match: %f, expected %f", acc.BalanceMap[utils.MONETARY][0].GetValue(), float64(10000-(debitsToDo*60)))
|
||||
}
|
||||
/*
|
||||
out, err := json.Marshal(acc)
|
||||
if err == nil {
|
||||
t.Log("Account: %s", string(out))
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
func TestSplitSpans(t *testing.T) {
|
||||
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)
|
||||
|
||||
@@ -40,7 +40,7 @@ type itemLock struct {
|
||||
// unlock() executes combined lock with autoremoving lock from Guardian
|
||||
func (il *itemLock) unlock() {
|
||||
atomic.AddInt64(&il.cnt, -1)
|
||||
if il.count() == 0 { // last lock in the queue
|
||||
if atomic.LoadInt64(&il.cnt) == 0 { // last lock in the queue
|
||||
Guardian.Lock()
|
||||
delete(Guardian.locksMap, il.keyID)
|
||||
Guardian.Unlock()
|
||||
@@ -48,10 +48,6 @@ func (il *itemLock) unlock() {
|
||||
il.Unlock()
|
||||
}
|
||||
|
||||
func (il *itemLock) count() int64 {
|
||||
return atomic.LoadInt64(&il.cnt)
|
||||
}
|
||||
|
||||
// GuardianLock is an optimized locking system per locking key
|
||||
type GuardianLock struct {
|
||||
locksMap map[string]*itemLock
|
||||
|
||||
@@ -19,6 +19,7 @@ package guardian
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -94,7 +95,7 @@ func TestGuardianGuardIDs(t *testing.T) {
|
||||
for _, lockID := range lockIDs {
|
||||
if itmLock, hasKey := Guardian.locksMap[lockID]; !hasKey {
|
||||
t.Errorf("Cannot find lock for lockID: %s", lockID)
|
||||
} else if itmLock.count() != 1 {
|
||||
} else if atomic.LoadInt64(&itmLock.cnt) != 1 {
|
||||
t.Errorf("Unexpected itmLock found: %+v", itmLock)
|
||||
}
|
||||
}
|
||||
@@ -102,42 +103,41 @@ func TestGuardianGuardIDs(t *testing.T) {
|
||||
time.Sleep(20 * time.Microsecond) // give time for goroutine to lock
|
||||
if itmLock, hasKey := Guardian.locksMap["test1"]; !hasKey {
|
||||
t.Errorf("Cannot find lock for lockID: %s", "test1")
|
||||
} else if itmLock.count() != 1 {
|
||||
} else if atomic.LoadInt64(&itmLock.cnt) != 1 {
|
||||
t.Errorf("Unexpected itmLock found: %+v", itmLock)
|
||||
}
|
||||
if itmLock, hasKey := Guardian.locksMap["test2"]; !hasKey {
|
||||
t.Errorf("Cannot find lock for lockID: %s", "test2")
|
||||
} else if itmLock.count() != 2 {
|
||||
} else if atomic.LoadInt64(&itmLock.cnt) != 2 {
|
||||
t.Errorf("Unexpected itmLock found: %+v", itmLock)
|
||||
}
|
||||
if itmLock, hasKey := Guardian.locksMap["test3"]; !hasKey {
|
||||
t.Errorf("Cannot find lock for lockID: %s", "test3")
|
||||
} else if itmLock.count() != 2 {
|
||||
} else if atomic.LoadInt64(&itmLock.cnt) != 2 {
|
||||
t.Errorf("Unexpected itmLock found: %+v", itmLock)
|
||||
}
|
||||
Guardian.GuardIDs(0, lockIDs...)
|
||||
if totalLockDur := time.Now().Sub(tStart); totalLockDur < lockDur {
|
||||
t.Errorf("Lock duration too small")
|
||||
}
|
||||
//time.Sleep(1000 * time.Microsecond)
|
||||
if len(Guardian.locksMap) != 3 {
|
||||
t.Errorf("locksMap should be have 3 elements, have: %+v", Guardian.locksMap)
|
||||
} else if itmLock, hasKey := Guardian.locksMap["test1"]; !hasKey {
|
||||
t.Errorf("Cannot find lock for lockID: %s", "test1")
|
||||
} else if itmLock.count() != 1 {
|
||||
t.Errorf("Unexpected itmLock found: %+v", itmLock)
|
||||
} else if itmLock, hasKey := Guardian.locksMap["test2"]; !hasKey {
|
||||
} else if cnt := atomic.LoadInt64(&itmLock.cnt); cnt != 1 {
|
||||
t.Errorf("Unexpected counter: %d for itmLock with id %s", cnt, "test1")
|
||||
} else if _, hasKey := Guardian.locksMap["test2"]; !hasKey {
|
||||
t.Errorf("Cannot find lock for lockID: %s", "test2")
|
||||
} else if itmLock.count() != 1 {
|
||||
t.Errorf("Unexpected itmLock found: %+v", itmLock)
|
||||
} else if cnt = atomic.LoadInt64(&itmLock.cnt); cnt != 1 {
|
||||
t.Errorf("Unexpected counter: %d for itmLock with id %s", cnt, "test2")
|
||||
} else if itmLock, hasKey := Guardian.locksMap["test3"]; !hasKey {
|
||||
t.Errorf("Cannot find lock for lockID: %s", "test2")
|
||||
} else if itmLock.count() != 1 {
|
||||
t.Errorf("Unexpected itmLock found: %+v", itmLock)
|
||||
t.Errorf("Cannot find lock for lockID: %s", "test3")
|
||||
} else if cnt = atomic.LoadInt64(&itmLock.cnt); cnt != 1 {
|
||||
t.Errorf("Unexpected counter: %d for itmLock with id %s", cnt, "test3")
|
||||
}
|
||||
Guardian.UnguardIDs(lockIDs...)
|
||||
if len(Guardian.locksMap) != 0 {
|
||||
t.Errorf("locksMap should be have 0 elements, have: %+v", Guardian.locksMap)
|
||||
t.Errorf("locksMap should have 0 elements, has: %+v", Guardian.locksMap)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user