package queue_test
import (
"testing"
"time"
"github.com/lightningnetwork/lnd/queue"
)
type testItem uint32
func TestGCQueueGCCycle(t *testing.T) {
t.Parallel()
const (
gcInterval = time.Second
expiryInterval = 250 * time.Millisecond
numItems = 6
)
newItem := func() interface{} { return new(testItem) }
bp := queue.NewGCQueue(newItem, 100, gcInterval, expiryInterval)
itemSet1 := takeN(t, bp, numItems)
returnAll(bp, itemSet1)
<-time.After(gcInterval + expiryInterval)
itemSet2 := takeN(t, bp, numItems)
for item := range itemSet2 {
if _, ok := itemSet1[item]; ok {
t.Fatalf("items taken should not have been reused")
}
}
}
func TestGCQueuePartialGCCycle(t *testing.T) {
t.Parallel()
const (
gcInterval = time.Second
expiryInterval = 250 * time.Millisecond
numItems = 6
)
newItem := func() interface{} { return new(testItem) }
bp := queue.NewGCQueue(newItem, 100, gcInterval, expiryInterval)
itemSet1 := takeN(t, bp, numItems)
halfItemSet1 := returnN(t, bp, itemSet1, numItems/2)
<-time.After(gcInterval - expiryInterval/2)
returnAll(bp, halfItemSet1)
<-time.After(expiryInterval / 2)
itemSet2 := takeN(t, bp, numItems)
var numReused int
for item := range itemSet2 {
if _, ok := halfItemSet1[item]; ok {
numReused++
}
}
if numReused != numItems/2 {
t.Fatalf("expected %d items to be reused, got %d",
numItems/2, numReused)
}
}
func takeN(t *testing.T, q *queue.GCQueue, n int) map[interface{}]struct{} {
t.Helper()
items := make(map[interface{}]struct{})
for i := 0; i < n; i++ {
<-time.After(time.Millisecond)
items[q.Take()] = struct{}{}
}
if len(items) != n {
t.Fatalf("items taken from gc queue should be distinct, "+
"want %d unique items, got %d", n, len(items))
}
return items
}
func returnAll(q *queue.GCQueue, items map[interface{}]struct{}) {
for item := range items {
q.Return(item)
<-time.After(time.Millisecond)
}
}
func returnN(t *testing.T, q *queue.GCQueue,
items map[interface{}]struct{}, n int) map[interface{}]struct{} {
t.Helper()
var remainingItems = make(map[interface{}]struct{})
var numReturned int
for item := range items {
if numReturned < n {
q.Return(item)
numReturned++
<-time.After(time.Millisecond)
} else {
remainingItems[item] = struct{}{}
}
}
if numReturned < n {
t.Fatalf("insufficient number of items to return, need %d, "+
"got %d", n, numReturned)
}
return remainingItems
}